ffi-rzmq 0.9.3 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +51 -0
- data/README.rdoc +17 -7
- data/examples/v2api/local_lat_poll.rb +3 -3
- data/examples/v2api/local_throughput.rb +2 -2
- data/examples/v2api/pub.rb +46 -0
- data/examples/v2api/publish_subscribe.rb +1 -1
- data/examples/v2api/remote_throughput.rb +1 -1
- data/examples/v2api/reqrep_poll.rb +2 -2
- data/examples/v2api/request_response.rb +2 -2
- data/examples/v2api/sub.rb +74 -0
- data/examples/v2api/throughput_measurement.rb +3 -3
- data/examples/v2api/xreqxrep_poll.rb +5 -5
- data/examples/v3api/local_lat_poll.rb +3 -3
- data/examples/v3api/pub.rb +46 -0
- data/examples/v3api/publish_subscribe.rb +1 -1
- data/examples/v3api/reqrep_poll.rb +2 -2
- data/examples/v3api/sub.rb +69 -0
- data/examples/v3api/xreqxrep_poll.rb +5 -5
- data/ffi-rzmq.gemspec +2 -2
- data/lib/ffi-rzmq/constants.rb +56 -18
- data/lib/ffi-rzmq/context.rb +63 -24
- data/lib/ffi-rzmq/device.rb +19 -19
- data/lib/ffi-rzmq/libzmq.rb +109 -34
- data/lib/ffi-rzmq/message.rb +23 -2
- data/lib/ffi-rzmq/poll.rb +7 -9
- data/lib/ffi-rzmq/socket.rb +284 -518
- data/lib/ffi-rzmq/util.rb +42 -36
- data/lib/ffi-rzmq/version.rb +1 -1
- data/spec/context_spec.rb +20 -16
- data/spec/device_spec.rb +64 -76
- data/spec/multipart_spec.rb +0 -54
- data/spec/nonblocking_recv_spec.rb +119 -80
- data/spec/poll_spec.rb +93 -12
- data/spec/pushpull_spec.rb +65 -111
- data/spec/reqrep_spec.rb +45 -56
- data/spec/socket_spec.rb +104 -71
- data/spec/spec_helper.rb +52 -4
- metadata +155 -135
data/lib/ffi-rzmq/libzmq.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module ZMQ
|
2
2
|
|
3
3
|
# Wraps the libzmq library and attaches to the functions that are
|
4
|
-
# common across the 2.x
|
4
|
+
# common across the 2.x and 3.x APIs.
|
5
5
|
#
|
6
6
|
module LibZMQ
|
7
7
|
extend FFI::Library
|
@@ -10,18 +10,32 @@ module ZMQ
|
|
10
10
|
# bias the library discovery to a path inside the gem first, then
|
11
11
|
# to the usual system paths
|
12
12
|
inside_gem = File.join(File.dirname(__FILE__), '..', '..', 'ext')
|
13
|
+
if FFI::Platform::IS_WINDOWS
|
14
|
+
local_path=ENV['PATH'].split(';')
|
15
|
+
else
|
16
|
+
local_path=ENV['PATH'].split(':')
|
17
|
+
end
|
13
18
|
ZMQ_LIB_PATHS = [
|
14
|
-
|
19
|
+
inside_gem, '/usr/local/lib', '/opt/local/lib', '/usr/local/homebrew/lib', '/usr/lib64'
|
15
20
|
].map{|path| "#{path}/libzmq.#{FFI::Platform::LIBSUFFIX}"}
|
16
21
|
ffi_lib(ZMQ_LIB_PATHS + %w{libzmq})
|
17
22
|
rescue LoadError
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
if ZMQ_LIB_PATHS.push(*local_path).any? {|path|
|
24
|
+
File.file? File.join(path, "libzmq.#{FFI::Platform::LIBSUFFIX}")}
|
25
|
+
warn "Unable to load this gem. The libzmq library exists, but cannot be loaded."
|
26
|
+
warn "If this is Windows:"
|
27
|
+
warn "- Check that you have MSVC runtime installed or statically linked"
|
28
|
+
warn "- Check that your DLL is compiled for #{FFI::Platform::ADDRESS_SIZE} bit"
|
29
|
+
else
|
30
|
+
warn "Unable to load this gem. The libzmq library (or DLL) could not be found."
|
31
|
+
warn "If this is a Windows platform, make sure libzmq.dll is on the PATH."
|
32
|
+
warn "If the DLL was built with mingw, make sure the other two dependent DLLs,"
|
33
|
+
warn "libgcc_s_sjlj-1.dll and libstdc++6.dll, are also on the PATH."
|
34
|
+
warn "For non-Windows platforms, make sure libzmq is located in this search path:"
|
35
|
+
warn ZMQ_LIB_PATHS.inspect
|
36
|
+
end
|
37
|
+
raise LoadError, "The libzmq library (or DLL) could not be loaded"
|
23
38
|
end
|
24
|
-
|
25
39
|
# Size_t not working properly on Windows
|
26
40
|
find_type(:size_t) rescue typedef(:ulong, :size_t)
|
27
41
|
|
@@ -38,20 +52,14 @@ module ZMQ
|
|
38
52
|
# otherwise the runtime hangs (and requires a kill -9 to terminate)
|
39
53
|
#
|
40
54
|
@blocking = true
|
41
|
-
attach_function :
|
42
|
-
@blocking = true
|
43
|
-
attach_function :zmq_socket, [:pointer, :int], :pointer
|
44
|
-
@blocking = true
|
45
|
-
attach_function :zmq_term, [:pointer], :int
|
55
|
+
attach_function :zmq_version, [:pointer, :pointer, :pointer], :void
|
46
56
|
@blocking = true
|
47
57
|
attach_function :zmq_errno, [], :int
|
48
58
|
@blocking = true
|
49
59
|
attach_function :zmq_strerror, [:int], :pointer
|
50
|
-
@blocking = true
|
51
|
-
attach_function :zmq_version, [:pointer, :pointer, :pointer], :void
|
52
60
|
|
53
61
|
def self.version
|
54
|
-
|
62
|
+
if @version.nil?
|
55
63
|
major = FFI::MemoryPointer.new :int
|
56
64
|
minor = FFI::MemoryPointer.new :int
|
57
65
|
patch = FFI::MemoryPointer.new :int
|
@@ -64,12 +72,15 @@ module ZMQ
|
|
64
72
|
|
65
73
|
def self.version2?() version[:major] == 2 && version[:minor] >= 1 end
|
66
74
|
|
67
|
-
def self.version3?() version[:major] == 3 && version[:minor] >=
|
68
|
-
|
69
|
-
def self.version4?() version[:major] == 4 end
|
75
|
+
def self.version3?() version[:major] == 3 && version[:minor] >= 2 end
|
70
76
|
|
77
|
+
# Context initialization and destruction
|
78
|
+
@blocking = true
|
79
|
+
attach_function :zmq_init, [:int], :pointer
|
80
|
+
@blocking = true
|
81
|
+
attach_function :zmq_term, [:pointer], :int
|
71
82
|
|
72
|
-
# Message
|
83
|
+
# Message API
|
73
84
|
@blocking = true
|
74
85
|
attach_function :zmq_msg_init, [:pointer], :int
|
75
86
|
@blocking = true
|
@@ -96,27 +107,41 @@ module ZMQ
|
|
96
107
|
:vsm_data, [:uint8, 30]
|
97
108
|
end # class Msg
|
98
109
|
|
99
|
-
# Socket
|
110
|
+
# Socket API
|
111
|
+
@blocking = true
|
112
|
+
attach_function :zmq_socket, [:pointer, :int], :pointer
|
100
113
|
@blocking = true
|
101
114
|
attach_function :zmq_setsockopt, [:pointer, :int, :pointer, :int], :int
|
102
115
|
@blocking = true
|
116
|
+
attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int
|
117
|
+
@blocking = true
|
103
118
|
attach_function :zmq_bind, [:pointer, :string], :int
|
104
119
|
@blocking = true
|
105
120
|
attach_function :zmq_connect, [:pointer, :string], :int
|
106
121
|
@blocking = true
|
107
122
|
attach_function :zmq_close, [:pointer], :int
|
108
123
|
|
109
|
-
#
|
124
|
+
# Device API
|
125
|
+
@blocking = true
|
126
|
+
attach_function :zmq_device, [:int, :pointer, :pointer], :int
|
127
|
+
|
128
|
+
# Poll API
|
110
129
|
@blocking = true
|
111
130
|
attach_function :zmq_poll, [:pointer, :int, :long], :int
|
112
131
|
|
113
132
|
module PollItemLayout
|
114
133
|
def self.included(base)
|
134
|
+
if FFI::Platform::IS_WINDOWS && FFI::Platform::ADDRESS_SIZE==64
|
135
|
+
# On Windows, zmq.h defines fd as a SOCKET, which is 64 bits on x64.
|
136
|
+
fd_type=:uint64
|
137
|
+
else
|
138
|
+
fd_type=:int
|
139
|
+
end
|
115
140
|
base.class_eval do
|
116
141
|
layout :socket, :pointer,
|
117
|
-
|
118
|
-
|
119
|
-
|
142
|
+
:fd, fd_type,
|
143
|
+
:events, :short,
|
144
|
+
:revents, :short
|
120
145
|
end
|
121
146
|
end
|
122
147
|
end # module PollItemLayout
|
@@ -125,7 +150,7 @@ module ZMQ
|
|
125
150
|
include PollItemLayout
|
126
151
|
|
127
152
|
def socket() self[:socket]; end
|
128
|
-
|
153
|
+
|
129
154
|
def fd() self[:fd]; end
|
130
155
|
|
131
156
|
def readable?
|
@@ -157,13 +182,9 @@ module ZMQ
|
|
157
182
|
module LibZMQ
|
158
183
|
# Socket api
|
159
184
|
@blocking = true
|
160
|
-
attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int
|
161
|
-
@blocking = true
|
162
185
|
attach_function :zmq_recv, [:pointer, :pointer, :int], :int
|
163
186
|
@blocking = true
|
164
187
|
attach_function :zmq_send, [:pointer, :pointer, :int], :int
|
165
|
-
@blocking = true
|
166
|
-
attach_function :zmq_device, [:int, :pointer, :pointer], :int
|
167
188
|
end
|
168
189
|
end
|
169
190
|
|
@@ -173,9 +194,37 @@ module ZMQ
|
|
173
194
|
if LibZMQ.version3?
|
174
195
|
|
175
196
|
module LibZMQ
|
176
|
-
#
|
197
|
+
# New Context API
|
198
|
+
@blocking = true
|
199
|
+
attach_function :zmq_ctx_new, [], :pointer
|
200
|
+
@blocking = true
|
201
|
+
attach_function :zmq_ctx_destroy, [:pointer], :int
|
202
|
+
@blocking = true
|
203
|
+
attach_function :zmq_ctx_set, [:pointer, :int, :int], :int
|
204
|
+
@blocking = true
|
205
|
+
attach_function :zmq_ctx_get, [:pointer, :int], :int
|
206
|
+
|
207
|
+
# Message API
|
177
208
|
@blocking = true
|
178
|
-
attach_function :
|
209
|
+
attach_function :zmq_msg_send, [:pointer, :pointer, :int], :int
|
210
|
+
@blocking = true
|
211
|
+
attach_function :zmq_msg_recv, [:pointer, :pointer, :int], :int
|
212
|
+
@blocking = true
|
213
|
+
attach_function :zmq_msg_more, [:pointer], :int
|
214
|
+
@blocking = true
|
215
|
+
attach_function :zmq_msg_get, [:pointer, :int], :int
|
216
|
+
@blocking = true
|
217
|
+
attach_function :zmq_msg_set, [:pointer, :int, :int], :int
|
218
|
+
|
219
|
+
# Monitoring API
|
220
|
+
@blocking = true
|
221
|
+
attach_function :zmq_ctx_set_monitor, [:pointer, :pointer], :int
|
222
|
+
|
223
|
+
# Socket API
|
224
|
+
@blocking = true
|
225
|
+
attach_function :zmq_unbind, [:pointer, :string], :int
|
226
|
+
@blocking = true
|
227
|
+
attach_function :zmq_disconnect, [:pointer, :string], :int
|
179
228
|
@blocking = true
|
180
229
|
attach_function :zmq_recvmsg, [:pointer, :pointer, :int], :int
|
181
230
|
@blocking = true
|
@@ -184,6 +233,33 @@ module ZMQ
|
|
184
233
|
attach_function :zmq_sendmsg, [:pointer, :pointer, :int], :int
|
185
234
|
@blocking = true
|
186
235
|
attach_function :zmq_send, [:pointer, :pointer, :size_t, :int], :int
|
236
|
+
|
237
|
+
module EventDataLayout
|
238
|
+
def self.included(base)
|
239
|
+
base.class_eval do
|
240
|
+
layout :addr, :string,
|
241
|
+
:field2, :int
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end # module EventDataLayout
|
245
|
+
|
246
|
+
class EventData < FFI::Struct
|
247
|
+
include EventDataLayout
|
248
|
+
|
249
|
+
def addr() self[:addr]; end
|
250
|
+
alias :address :addr
|
251
|
+
|
252
|
+
def fd() self[:field2]; end
|
253
|
+
alias :err :fd
|
254
|
+
alias :interval :fd
|
255
|
+
|
256
|
+
def inspect
|
257
|
+
"addr [#{addr}], fd [#{fd}], field2 [#{fd}]"
|
258
|
+
end
|
259
|
+
|
260
|
+
def to_s; inspect; end
|
261
|
+
end # class EventData
|
262
|
+
|
187
263
|
end
|
188
264
|
end
|
189
265
|
|
@@ -194,8 +270,7 @@ module ZMQ
|
|
194
270
|
unless LibZMQ.version2? || LibZMQ.version3?
|
195
271
|
hash = LibZMQ.version
|
196
272
|
version = "#{hash[:major]}.#{hash[:minor]}.#{hash[:patch]}"
|
197
|
-
|
198
|
-
exit 255
|
273
|
+
raise LoadError, "The libzmq version #{version} is incompatible with ffi-rzmq."
|
199
274
|
end
|
200
275
|
|
201
276
|
end # module ZMQ
|
data/lib/ffi-rzmq/message.rb
CHANGED
@@ -30,7 +30,7 @@ module ZMQ
|
|
30
30
|
#
|
31
31
|
# received_message = Message.create
|
32
32
|
# if received_message
|
33
|
-
# rc = socket.
|
33
|
+
# rc = socket.recvmsg(received_message)
|
34
34
|
# if ZMQ::Util.resultcode_ok?(rc)
|
35
35
|
# puts "Message contained: #{received_message.copy_out_string}"
|
36
36
|
# else
|
@@ -84,7 +84,6 @@ module ZMQ
|
|
84
84
|
# puts "value1 is #{message.value1}"
|
85
85
|
#
|
86
86
|
class Message
|
87
|
-
include ZMQ::Util
|
88
87
|
|
89
88
|
# Recommended way to create a standard message. A Message object is
|
90
89
|
# returned upon success, nil when allocation fails.
|
@@ -199,6 +198,28 @@ module ZMQ
|
|
199
198
|
def self.msg_size() @msg_size; end
|
200
199
|
|
201
200
|
end # class Message
|
201
|
+
|
202
|
+
if LibZMQ.version3?
|
203
|
+
class Message
|
204
|
+
# Version3 only
|
205
|
+
#
|
206
|
+
def get(property)
|
207
|
+
LibZMQ.zmq_msg_get(@pointer, property)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Version3 only
|
211
|
+
#
|
212
|
+
# Returns true if this message has additional parts coming.
|
213
|
+
#
|
214
|
+
def more?
|
215
|
+
Util.resultcode_ok?(get(MORE))
|
216
|
+
end
|
217
|
+
|
218
|
+
def set(property, value)
|
219
|
+
LibZMQ.zmq_msg_set(@pointer, property, value)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
202
223
|
|
203
224
|
|
204
225
|
|
data/lib/ffi-rzmq/poll.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
module ZMQ
|
3
3
|
|
4
4
|
class Poller
|
5
|
-
include ZMQ::Util
|
6
5
|
|
7
6
|
attr_reader :readables, :writables
|
8
7
|
|
@@ -15,7 +14,7 @@ module ZMQ
|
|
15
14
|
end
|
16
15
|
|
17
16
|
# Checks each registered socket for selectability based on the poll items'
|
18
|
-
# registered +events+. Will block for up to +timeout+ milliseconds
|
17
|
+
# registered +events+. Will block for up to +timeout+ milliseconds.
|
19
18
|
# A millisecond is 1/1000 of a second, so to block for 1 second
|
20
19
|
# pass the value "1000" to #poll.
|
21
20
|
#
|
@@ -100,7 +99,7 @@ module ZMQ
|
|
100
99
|
|
101
100
|
item = @items.get(@sockets.index(sock))
|
102
101
|
|
103
|
-
if item
|
102
|
+
if item && (item[:events] & events) > 0
|
104
103
|
# change the value in place
|
105
104
|
item[:events] ^= events
|
106
105
|
|
@@ -139,11 +138,11 @@ module ZMQ
|
|
139
138
|
# when a socket has been deregistered and has no more events
|
140
139
|
# registered anywhere.
|
141
140
|
#
|
141
|
+
# Can also be called directly to remove the socket from the polling
|
142
|
+
# array.
|
143
|
+
#
|
142
144
|
def delete sock
|
143
|
-
|
144
|
-
removed_writable = deregister_writable sock
|
145
|
-
|
146
|
-
unless (removed_readable || removed_writable) || (size = @sockets.size).zero?
|
145
|
+
unless (size = @sockets.size).zero?
|
147
146
|
@sockets.delete_if { |socket| socket.socket.address == sock.socket.address }
|
148
147
|
socket_deleted = size != @sockets.size
|
149
148
|
|
@@ -154,8 +153,7 @@ module ZMQ
|
|
154
153
|
socket_deleted && item_deleted && raw_deleted
|
155
154
|
|
156
155
|
else
|
157
|
-
|
158
|
-
removed_readable || removed_writable
|
156
|
+
false
|
159
157
|
end
|
160
158
|
end
|
161
159
|
|
data/lib/ffi-rzmq/socket.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
module ZMQ
|
3
3
|
|
4
4
|
module CommonSocketBehavior
|
5
|
-
include ZMQ::Util
|
6
5
|
|
7
6
|
attr_reader :socket, :name
|
8
7
|
|
@@ -82,6 +81,7 @@ module ZMQ
|
|
82
81
|
raise ContextError.new 'zmq_socket', 0, ETERM, "Context pointer was null"
|
83
82
|
end
|
84
83
|
|
84
|
+
@longlong_cache = @int_cache = nil
|
85
85
|
@more_parts_array = []
|
86
86
|
@option_lookup = []
|
87
87
|
populate_option_lookup
|
@@ -157,12 +157,12 @@ module ZMQ
|
|
157
157
|
#
|
158
158
|
# message_parts = []
|
159
159
|
# message = Message.new
|
160
|
-
# rc = socket.
|
160
|
+
# rc = socket.recvmsg(message)
|
161
161
|
# if ZMQ::Util.resultcode_ok?(rc)
|
162
162
|
# message_parts << message
|
163
163
|
# while more_parts?
|
164
164
|
# message = Message.new
|
165
|
-
# rc = socket.
|
165
|
+
# rc = socket.recvmsg(message)
|
166
166
|
# message_parts.push(message) if resulcode_ok?(rc)
|
167
167
|
# end
|
168
168
|
# end
|
@@ -183,7 +183,7 @@ module ZMQ
|
|
183
183
|
|
184
184
|
# Connects the socket to an +address+.
|
185
185
|
#
|
186
|
-
# socket.connect("tcp://127.0.0.1:5555")
|
186
|
+
# rc = socket.connect("tcp://127.0.0.1:5555")
|
187
187
|
#
|
188
188
|
def connect address
|
189
189
|
rc = LibZMQ.zmq_connect @socket, address
|
@@ -210,6 +210,238 @@ module ZMQ
|
|
210
210
|
end
|
211
211
|
end
|
212
212
|
|
213
|
+
# Queues the message for transmission. Message is assumed to conform to the
|
214
|
+
# same public API as #Message.
|
215
|
+
#
|
216
|
+
# +flags+ may take two values:
|
217
|
+
# * 0 (default) - blocking operation
|
218
|
+
# * ZMQ::NonBlocking - non-blocking operation
|
219
|
+
# * ZMQ::SNDMORE - this message is part of a multi-part message
|
220
|
+
#
|
221
|
+
# Returns 0 when the message was successfully enqueued.
|
222
|
+
# Returns -1 under two conditions.
|
223
|
+
# 1. The message could not be enqueued
|
224
|
+
# 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
|
225
|
+
#
|
226
|
+
# With a -1 return code, the user must check ZMQ.errno to determine the
|
227
|
+
# cause.
|
228
|
+
#
|
229
|
+
def sendmsg message, flags = 0
|
230
|
+
__sendmsg__(@socket, message.address, flags)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Helper method to make a new #Message instance out of the +string+ passed
|
234
|
+
# in for transmission.
|
235
|
+
#
|
236
|
+
# +flags+ may be ZMQ::NonBlocking and ZMQ::SNDMORE.
|
237
|
+
#
|
238
|
+
# Returns 0 when the message was successfully enqueued.
|
239
|
+
# Returns -1 under two conditions.
|
240
|
+
# 1. The message could not be enqueued
|
241
|
+
# 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
|
242
|
+
#
|
243
|
+
# With a -1 return code, the user must check ZMQ.errno to determine the
|
244
|
+
# cause.
|
245
|
+
#
|
246
|
+
def send_string string, flags = 0
|
247
|
+
message = Message.new string
|
248
|
+
send_and_close message, flags
|
249
|
+
end
|
250
|
+
|
251
|
+
# Send a sequence of strings as a multipart message out of the +parts+
|
252
|
+
# passed in for transmission. Every element of +parts+ should be
|
253
|
+
# a String.
|
254
|
+
#
|
255
|
+
# +flags+ may be ZMQ::NonBlocking.
|
256
|
+
#
|
257
|
+
# Returns 0 when the messages were successfully enqueued.
|
258
|
+
# Returns -1 under two conditions.
|
259
|
+
# 1. A message could not be enqueued
|
260
|
+
# 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
|
261
|
+
#
|
262
|
+
# With a -1 return code, the user must check ZMQ.errno to determine the
|
263
|
+
# cause.
|
264
|
+
#
|
265
|
+
def send_strings parts, flags = 0
|
266
|
+
return -1 if !parts || parts.empty?
|
267
|
+
flags = NonBlocking if dontwait?(flags)
|
268
|
+
|
269
|
+
parts[0..-2].each do |part|
|
270
|
+
rc = send_string part, (flags | ZMQ::SNDMORE)
|
271
|
+
return rc unless Util.resultcode_ok?(rc)
|
272
|
+
end
|
273
|
+
|
274
|
+
send_string parts[-1], flags
|
275
|
+
end
|
276
|
+
|
277
|
+
# Send a sequence of messages as a multipart message out of the +parts+
|
278
|
+
# passed in for transmission. Every element of +parts+ should be
|
279
|
+
# a Message (or subclass).
|
280
|
+
#
|
281
|
+
# +flags+ may be ZMQ::NonBlocking.
|
282
|
+
#
|
283
|
+
# Returns 0 when the messages were successfully enqueued.
|
284
|
+
# Returns -1 under two conditions.
|
285
|
+
# 1. A message could not be enqueued
|
286
|
+
# 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
|
287
|
+
#
|
288
|
+
# With a -1 return code, the user must check ZMQ.errno to determine the
|
289
|
+
# cause.
|
290
|
+
#
|
291
|
+
def sendmsgs parts, flags = 0
|
292
|
+
return -1 if !parts || parts.empty?
|
293
|
+
flags = NonBlocking if dontwait?(flags)
|
294
|
+
|
295
|
+
parts[0..-2].each do |part|
|
296
|
+
rc = sendmsg part, (flags | ZMQ::SNDMORE)
|
297
|
+
return rc unless Util.resultcode_ok?(rc)
|
298
|
+
end
|
299
|
+
|
300
|
+
sendmsg parts[-1], flags
|
301
|
+
end
|
302
|
+
|
303
|
+
# Sends a message. This will automatically close the +message+ for both successful
|
304
|
+
# and failed sends.
|
305
|
+
#
|
306
|
+
# Returns 0 when the message was successfully enqueued.
|
307
|
+
# Returns -1 under two conditions.
|
308
|
+
# 1. The message could not be enqueued
|
309
|
+
# 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
|
310
|
+
#
|
311
|
+
# With a -1 return code, the user must check ZMQ.errno to determine the
|
312
|
+
# cause.
|
313
|
+
#
|
314
|
+
def send_and_close message, flags = 0
|
315
|
+
rc = sendmsg message, flags
|
316
|
+
message.close
|
317
|
+
rc
|
318
|
+
end
|
319
|
+
|
320
|
+
# Dequeues a message from the underlying queue. By default, this is a blocking operation.
|
321
|
+
#
|
322
|
+
# +flags+ may take two values:
|
323
|
+
# 0 (default) - blocking operation
|
324
|
+
# ZMQ::NonBlocking - non-blocking operation
|
325
|
+
#
|
326
|
+
# Returns 0 when the message was successfully dequeued.
|
327
|
+
# Returns -1 under two conditions.
|
328
|
+
# 1. The message could not be dequeued
|
329
|
+
# 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
|
330
|
+
#
|
331
|
+
# With a -1 return code, the user must check ZMQ.errno to determine the
|
332
|
+
# cause.
|
333
|
+
#
|
334
|
+
# The application code is responsible for handling the +message+ object lifecycle
|
335
|
+
# when #recv returns an error code.
|
336
|
+
#
|
337
|
+
def recvmsg message, flags = 0
|
338
|
+
#LibZMQ.zmq_recvmsg @socket, message.address, flags
|
339
|
+
__recvmsg__(@socket, message.address, flags)
|
340
|
+
end
|
341
|
+
|
342
|
+
# Helper method to make a new #Message instance and convert its payload
|
343
|
+
# to a string.
|
344
|
+
#
|
345
|
+
# +flags+ may be ZMQ::NonBlocking.
|
346
|
+
#
|
347
|
+
# Returns 0 when the message was successfully dequeued.
|
348
|
+
# Returns -1 under two conditions.
|
349
|
+
# 1. The message could not be dequeued
|
350
|
+
# 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
|
351
|
+
#
|
352
|
+
# With a -1 return code, the user must check ZMQ.errno to determine the
|
353
|
+
# cause.
|
354
|
+
#
|
355
|
+
# The application code is responsible for handling the +message+ object lifecycle
|
356
|
+
# when #recv returns an error code.
|
357
|
+
#
|
358
|
+
def recv_string string, flags = 0
|
359
|
+
message = @receiver_klass.new
|
360
|
+
rc = recvmsg message, flags
|
361
|
+
string.replace(message.copy_out_string) if Util.resultcode_ok?(rc)
|
362
|
+
message.close
|
363
|
+
rc
|
364
|
+
end
|
365
|
+
|
366
|
+
# Receive a multipart message as a list of strings.
|
367
|
+
#
|
368
|
+
# +flag+ may be ZMQ::NonBlocking. Any other flag will be
|
369
|
+
# removed.
|
370
|
+
#
|
371
|
+
def recv_strings list, flag = 0
|
372
|
+
array = []
|
373
|
+
rc = recvmsgs array, flag
|
374
|
+
|
375
|
+
if Util.resultcode_ok?(rc)
|
376
|
+
array.each do |message|
|
377
|
+
list << message.copy_out_string
|
378
|
+
message.close
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
rc
|
383
|
+
end
|
384
|
+
|
385
|
+
# Receive a multipart message as an array of objects
|
386
|
+
# (by default these are instances of Message).
|
387
|
+
#
|
388
|
+
# +flag+ may be ZMQ::NonBlocking. Any other flag will be
|
389
|
+
# removed.
|
390
|
+
#
|
391
|
+
def recvmsgs list, flag = 0
|
392
|
+
flag = NonBlocking if dontwait?(flag)
|
393
|
+
|
394
|
+
message = @receiver_klass.new
|
395
|
+
rc = recvmsg message, flag
|
396
|
+
|
397
|
+
if Util.resultcode_ok?(rc)
|
398
|
+
list << message
|
399
|
+
|
400
|
+
# check rc *first*; necessary because the call to #more_parts? can reset
|
401
|
+
# the zmq_errno to a weird value, so the zmq_errno that was set on the
|
402
|
+
# call to #recv gets lost
|
403
|
+
while Util.resultcode_ok?(rc) && more_parts?
|
404
|
+
message = @receiver_klass.new
|
405
|
+
rc = recvmsg message, flag
|
406
|
+
|
407
|
+
if Util.resultcode_ok?(rc)
|
408
|
+
list << message
|
409
|
+
else
|
410
|
+
message.close
|
411
|
+
list.each { |msg| msg.close }
|
412
|
+
list.clear
|
413
|
+
end
|
414
|
+
end
|
415
|
+
else
|
416
|
+
message.close
|
417
|
+
end
|
418
|
+
|
419
|
+
rc
|
420
|
+
end
|
421
|
+
|
422
|
+
# Should only be used for XREQ, XREP, DEALER and ROUTER type sockets. Takes
|
423
|
+
# a +list+ for receiving the message body parts and a +routing_envelope+
|
424
|
+
# for receiving the message parts comprising the 0mq routing information.
|
425
|
+
#
|
426
|
+
def recv_multipart list, routing_envelope, flag = 0
|
427
|
+
parts = []
|
428
|
+
rc = recvmsgs parts, flag
|
429
|
+
|
430
|
+
if Util.resultcode_ok?(rc)
|
431
|
+
routing = true
|
432
|
+
parts.each do |part|
|
433
|
+
if routing
|
434
|
+
routing_envelope << part
|
435
|
+
routing = part.size > 0
|
436
|
+
else
|
437
|
+
list << part
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
rc
|
443
|
+
end
|
444
|
+
|
213
445
|
|
214
446
|
private
|
215
447
|
|
@@ -217,7 +449,7 @@ module ZMQ
|
|
217
449
|
# a small optimization so we only have to determine the option
|
218
450
|
# type a single time; gives approx 5% speedup to do it this way.
|
219
451
|
option_type = @option_lookup[name]
|
220
|
-
|
452
|
+
|
221
453
|
value, length = sockopt_buffers option_type
|
222
454
|
|
223
455
|
rc = LibZMQ.zmq_getsockopt @socket, name, value, length
|
@@ -276,14 +508,14 @@ module ZMQ
|
|
276
508
|
@int_cache
|
277
509
|
end
|
278
510
|
end
|
279
|
-
|
511
|
+
|
280
512
|
def populate_option_lookup
|
281
513
|
# integer options
|
282
|
-
[EVENTS, LINGER, RECONNECT_IVL, FD, TYPE, BACKLOG].each { |option| @option_lookup[option] = 0 }
|
514
|
+
[EVENTS, LINGER, RCVTIMEO, SNDTIMEO, RECONNECT_IVL, FD, TYPE, BACKLOG].each { |option| @option_lookup[option] = 0 }
|
283
515
|
|
284
516
|
# long long options
|
285
517
|
[RCVMORE, AFFINITY].each { |option| @option_lookup[option] = 1 }
|
286
|
-
|
518
|
+
|
287
519
|
# string options
|
288
520
|
[SUBSCRIBE, UNSUBSCRIBE].each { |option| @option_lookup[option] = 2 }
|
289
521
|
end
|
@@ -292,6 +524,11 @@ module ZMQ
|
|
292
524
|
@longlong_cache = nil
|
293
525
|
@int_cache = nil
|
294
526
|
end
|
527
|
+
|
528
|
+
def dontwait?(flags)
|
529
|
+
(NonBlocking & flags) == NonBlocking
|
530
|
+
end
|
531
|
+
alias :noblock? :dontwait?
|
295
532
|
end # module CommonSocketBehavior
|
296
533
|
|
297
534
|
|
@@ -313,14 +550,14 @@ module ZMQ
|
|
313
550
|
|
314
551
|
|
315
552
|
private
|
316
|
-
|
553
|
+
|
317
554
|
def populate_option_lookup
|
318
555
|
super()
|
319
|
-
|
556
|
+
|
320
557
|
# string options
|
321
558
|
[IDENTITY].each { |option| @option_lookup[option] = 2 }
|
322
559
|
end
|
323
|
-
|
560
|
+
|
324
561
|
end # module IdentitySupport
|
325
562
|
|
326
563
|
|
@@ -380,280 +617,26 @@ module ZMQ
|
|
380
617
|
rc
|
381
618
|
end
|
382
619
|
|
383
|
-
# Queues the message for transmission. Message is assumed to conform to the
|
384
|
-
# same public API as #Message.
|
385
|
-
#
|
386
|
-
# +flags+ may take two values:
|
387
|
-
# * 0 (default) - blocking operation
|
388
|
-
# * ZMQ::NOBLOCK - non-blocking operation
|
389
|
-
# * ZMQ::SNDMORE - this message is part of a multi-part message
|
390
|
-
#
|
391
|
-
# Returns 0 when the message was successfully enqueued.
|
392
|
-
# Returns -1 under two conditions.
|
393
|
-
# 1. The message could not be enqueued
|
394
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
395
|
-
#
|
396
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
397
|
-
# cause.
|
398
|
-
#
|
399
|
-
# The application code is responsible for handling the +message+ object
|
400
|
-
# lifecycle when #send returns. Regardless of the return code, the user
|
401
|
-
# is responsible for calling message.close to free the memory in use.
|
402
|
-
#
|
403
|
-
def send message, flags = 0
|
404
|
-
LibZMQ.zmq_send @socket, message.address, flags
|
405
|
-
end
|
406
|
-
|
407
|
-
# Helper method to make a new #Message instance out of the +message_string+ passed
|
408
|
-
# in for transmission.
|
409
|
-
#
|
410
|
-
# +flags+ may be ZMQ::NOBLOCK.
|
411
|
-
#
|
412
|
-
# Returns 0 when the message was successfully enqueued.
|
413
|
-
# Returns -1 under two conditions.
|
414
|
-
# 1. The message could not be enqueued
|
415
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
416
|
-
#
|
417
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
418
|
-
# cause.
|
419
|
-
#
|
420
|
-
def send_string message_string, flags = 0
|
421
|
-
message = Message.new message_string
|
422
|
-
send_and_close message, flags
|
423
|
-
end
|
424
|
-
|
425
|
-
# Send a sequence of strings as a multipart message out of the +parts+
|
426
|
-
# passed in for transmission. Every element of +parts+ should be
|
427
|
-
# a String.
|
428
|
-
#
|
429
|
-
# +flags+ may be ZMQ::NOBLOCK.
|
430
|
-
#
|
431
|
-
# Returns 0 when the message was successfully enqueued.
|
432
|
-
# Returns -1 under two conditions.
|
433
|
-
# 1. The message could not be enqueued
|
434
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
435
|
-
#
|
436
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
437
|
-
# cause.
|
438
|
-
#
|
439
|
-
def send_strings parts, flags = 0
|
440
|
-
return -1 if !parts || parts.empty?
|
441
|
-
|
442
|
-
parts[0..-2].each do |part|
|
443
|
-
rc = send_string part, flags | ZMQ::SNDMORE
|
444
|
-
return rc unless Util.resultcode_ok?(rc)
|
445
|
-
end
|
446
|
-
|
447
|
-
send_string parts[-1], flags
|
448
|
-
end
|
449
|
-
|
450
|
-
# Send a sequence of messages as a multipart message out of the +parts+
|
451
|
-
# passed in for transmission. Every element of +parts+ should be
|
452
|
-
# a Message (or subclass).
|
453
|
-
#
|
454
|
-
# +flags+ may be ZMQ::NOBLOCK.
|
455
|
-
#
|
456
|
-
# Returns 0 when the message was successfully enqueued.
|
457
|
-
# Returns -1 under two conditions.
|
458
|
-
# 1. The message could not be enqueued
|
459
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
460
|
-
#
|
461
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
462
|
-
# cause.
|
463
|
-
#
|
464
|
-
def sendmsgs parts, flags = 0
|
465
|
-
return -1 if !parts || parts.empty?
|
466
|
-
|
467
|
-
parts[0..-2].each do |part|
|
468
|
-
rc = send part, flags | ZMQ::SNDMORE
|
469
|
-
return rc unless Util.resultcode_ok?(rc)
|
470
|
-
end
|
471
|
-
|
472
|
-
send parts[-1], flags
|
473
|
-
end
|
474
|
-
|
475
|
-
# Sends a message. This will automatically close the +message+ for both successful
|
476
|
-
# and failed sends.
|
477
|
-
#
|
478
|
-
# Returns 0 when the message was successfully enqueued.
|
479
|
-
# Returns -1 under two conditions.
|
480
|
-
# 1. The message could not be enqueued
|
481
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
482
|
-
#
|
483
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
484
|
-
# cause.
|
485
|
-
#
|
486
|
-
def send_and_close message, flags = 0
|
487
|
-
rc = send message, flags
|
488
|
-
message.close
|
489
|
-
rc
|
490
|
-
end
|
491
|
-
|
492
|
-
# Dequeues a message from the underlying queue. By default, this is a blocking operation.
|
493
|
-
#
|
494
|
-
# +flags+ may take two values:
|
495
|
-
# 0 (default) - blocking operation
|
496
|
-
# ZMQ::NOBLOCK - non-blocking operation
|
497
|
-
#
|
498
|
-
# Returns 0 when the message was successfully dequeued.
|
499
|
-
# Returns -1 under two conditions.
|
500
|
-
# 1. The message could not be dequeued
|
501
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
502
|
-
#
|
503
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
504
|
-
# cause.
|
505
|
-
#
|
506
|
-
# The application code is responsible for handling the +message+ object lifecycle
|
507
|
-
# when #recv returns an error code.
|
508
|
-
#
|
509
|
-
def recv message, flags = 0
|
510
|
-
LibZMQ.zmq_recv @socket, message.address, flags
|
511
|
-
end
|
512
|
-
|
513
|
-
# Converts the received message to a string and replaces the +string+ arg
|
514
|
-
# contents.
|
515
|
-
#
|
516
|
-
# +string+ should be an empty string, .e.g. ''
|
517
|
-
# +flags+ may be ZMQ::NOBLOCK.
|
518
|
-
#
|
519
|
-
# Returns 0 when the message was successfully dequeued.
|
520
|
-
# Returns -1 under two conditions.
|
521
|
-
# 1. The message could not be dequeued
|
522
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
523
|
-
#
|
524
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
525
|
-
# cause.
|
526
|
-
#
|
527
|
-
def recv_string string, flags = 0
|
528
|
-
message = @receiver_klass.new
|
529
|
-
rc = recv message, flags
|
530
|
-
string.replace(message.copy_out_string) if Util.resultcode_ok?(rc)
|
531
|
-
message.close
|
532
|
-
rc
|
533
|
-
end
|
534
|
-
|
535
|
-
# Receive a multipart message as a list of strings.
|
536
|
-
#
|
537
|
-
# +list+ should be an object that responds to #append or #<< so received
|
538
|
-
# strings can be appended to it
|
539
|
-
# +flag+ may be ZMQ::NOBLOCK. Any other flag will be removed
|
540
|
-
#
|
541
|
-
# Returns 0 when all messages were successfully dequeued.
|
542
|
-
# Returns -1 under two conditions.
|
543
|
-
# 1. A message could not be dequeued
|
544
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
545
|
-
#
|
546
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
547
|
-
# cause. Also, the +list+ will not be modified when there was an error.
|
548
|
-
#
|
549
|
-
def recv_strings list, flag = 0
|
550
|
-
array = []
|
551
|
-
rc = recvmsgs array, flag
|
552
620
|
|
553
|
-
|
554
|
-
array.each do |message|
|
555
|
-
list << message.copy_out_string
|
556
|
-
message.close
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
rc
|
561
|
-
end
|
562
|
-
|
563
|
-
# Receive a multipart message as an array of objects
|
564
|
-
# (by default these are instances of Message).
|
565
|
-
#
|
566
|
-
# +list+ should be an object that responds to #append or #<< so received
|
567
|
-
# messages can be appended to it
|
568
|
-
# +flag+ may be ZMQ::NOBLOCK. Any other flag will be
|
569
|
-
# removed.
|
570
|
-
#
|
571
|
-
# Returns 0 when all messages were successfully dequeued.
|
572
|
-
# Returns -1 under two conditions.
|
573
|
-
# 1. A message could not be dequeued
|
574
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
575
|
-
#
|
576
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
577
|
-
# cause. Also, the +list+ will not be modified when there was an error.
|
578
|
-
#
|
579
|
-
def recvmsgs list, flag = 0
|
580
|
-
flag = NOBLOCK if noblock?(flag)
|
581
|
-
|
582
|
-
message = @receiver_klass.new
|
583
|
-
rc = recv message, flag
|
584
|
-
|
585
|
-
if Util.resultcode_ok?(rc)
|
586
|
-
list << message
|
587
|
-
|
588
|
-
# check rc *first*; necessary because the call to #more_parts? can reset
|
589
|
-
# the zmq_errno to a weird value, so the zmq_errno that was set on the
|
590
|
-
# call to #recv gets lost
|
591
|
-
while Util.resultcode_ok?(rc) && more_parts?
|
592
|
-
message = @receiver_klass.new
|
593
|
-
rc = recv message, flag
|
594
|
-
|
595
|
-
if Util.resultcode_ok?(rc)
|
596
|
-
list << message
|
597
|
-
else
|
598
|
-
message.close
|
599
|
-
list.each { |msg| msg.close }
|
600
|
-
list.clear
|
601
|
-
end
|
602
|
-
end
|
603
|
-
else
|
604
|
-
message.close
|
605
|
-
end
|
621
|
+
private
|
606
622
|
|
607
|
-
|
623
|
+
def __sendmsg__(socket, address, flags)
|
624
|
+
LibZMQ.zmq_send(socket, address, flags)
|
608
625
|
end
|
609
626
|
|
610
|
-
|
611
|
-
|
612
|
-
# for receiving the message parts comprising the 0mq routing information.
|
613
|
-
#
|
614
|
-
# Returns 0 when all messages were successfully dequeued.
|
615
|
-
# Returns -1 under two conditions.
|
616
|
-
# 1. A message could not be dequeued
|
617
|
-
# 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
|
618
|
-
#
|
619
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
620
|
-
# cause. Also, the +list+ *may* be modified when there was an error.
|
621
|
-
#
|
622
|
-
def recv_multipart list, routing_envelope, flag = 0
|
623
|
-
parts = []
|
624
|
-
rc = recvmsgs parts, flag
|
625
|
-
|
626
|
-
if Util.resultcode_ok?(rc)
|
627
|
-
routing = true
|
628
|
-
parts.each do |part|
|
629
|
-
if routing
|
630
|
-
routing_envelope << part
|
631
|
-
routing = part.size > 0
|
632
|
-
else
|
633
|
-
list << part
|
634
|
-
end
|
635
|
-
end
|
636
|
-
end
|
637
|
-
|
638
|
-
rc
|
627
|
+
def __recvmsg__(socket, address, flags)
|
628
|
+
LibZMQ.zmq_recv(socket, address, flags)
|
639
629
|
end
|
640
630
|
|
631
|
+
def populate_option_lookup
|
632
|
+
super()
|
641
633
|
|
642
|
-
|
634
|
+
# integer options
|
635
|
+
[RECONNECT_IVL_MAX].each { |option| @option_lookup[option] = 0 }
|
643
636
|
|
644
|
-
|
645
|
-
|
637
|
+
# long long options
|
638
|
+
[HWM, SWAP, RATE, RECOVERY_IVL, RECOVERY_IVL_MSEC, MCAST_LOOP, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 1 }
|
646
639
|
end
|
647
|
-
|
648
|
-
def populate_option_lookup
|
649
|
-
super()
|
650
|
-
|
651
|
-
# integer options
|
652
|
-
[RECONNECT_IVL_MAX].each { |option| @option_lookup[option] = 0 }
|
653
|
-
|
654
|
-
# long long options
|
655
|
-
[HWM, SWAP, RATE, RECOVERY_IVL, RECOVERY_IVL_MSEC, MCAST_LOOP, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 1 }
|
656
|
-
end
|
657
640
|
|
658
641
|
# these finalizer-related methods cannot live in the CommonSocketBehavior
|
659
642
|
# module; they *must* be in the class definition directly
|
@@ -702,6 +685,7 @@ module ZMQ
|
|
702
685
|
# ZMQ::RECONNECT_IVL - integer measured in milliseconds
|
703
686
|
# ZMQ::BACKLOG - integer
|
704
687
|
# ZMQ::RECOVER_IVL_MSEC - integer measured in milliseconds
|
688
|
+
# ZMQ::IPV4ONLY - integer
|
705
689
|
#
|
706
690
|
# Returns 0 when the operation completed successfully.
|
707
691
|
# Returns -1 when this operation failed.
|
@@ -724,263 +708,45 @@ module ZMQ
|
|
724
708
|
|
725
709
|
rc
|
726
710
|
end
|
727
|
-
|
728
|
-
#
|
729
|
-
# same public API as #Message.
|
730
|
-
#
|
731
|
-
# +flags+ may take two values:
|
732
|
-
# * 0 (default) - blocking operation
|
733
|
-
# * ZMQ::DONTWAIT - non-blocking operation
|
734
|
-
# * ZMQ::SNDMORE - this message is part of a multi-part message
|
735
|
-
#
|
736
|
-
# Returns 0 when the message was successfully enqueued.
|
737
|
-
# Returns -1 under two conditions.
|
738
|
-
# 1. The message could not be enqueued
|
739
|
-
# 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
|
740
|
-
#
|
741
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
742
|
-
# cause.
|
743
|
-
#
|
744
|
-
def sendmsg message, flags = 0
|
745
|
-
LibZMQ.zmq_sendmsg @socket, message.address, flags
|
746
|
-
end
|
747
|
-
|
748
|
-
# Helper method to make a new #Message instance out of the +string+ passed
|
749
|
-
# in for transmission.
|
750
|
-
#
|
751
|
-
# +flags+ may be ZMQ::DONTWAIT and ZMQ::SNDMORE.
|
752
|
-
#
|
753
|
-
# Returns 0 when the message was successfully enqueued.
|
754
|
-
# Returns -1 under two conditions.
|
755
|
-
# 1. The message could not be enqueued
|
756
|
-
# 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
|
757
|
-
#
|
758
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
759
|
-
# cause.
|
760
|
-
#
|
761
|
-
def send_string string, flags = 0
|
762
|
-
message = Message.new string
|
763
|
-
send_and_close message, flags
|
764
|
-
end
|
765
|
-
|
766
|
-
# Send a sequence of strings as a multipart message out of the +parts+
|
767
|
-
# passed in for transmission. Every element of +parts+ should be
|
768
|
-
# a String.
|
769
|
-
#
|
770
|
-
# +flags+ may be ZMQ::DONTWAIT.
|
771
|
-
#
|
772
|
-
# Returns 0 when the messages were successfully enqueued.
|
773
|
-
# Returns -1 under two conditions.
|
774
|
-
# 1. A message could not be enqueued
|
775
|
-
# 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
|
776
|
-
#
|
777
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
778
|
-
# cause.
|
779
|
-
#
|
780
|
-
def send_strings parts, flags = 0
|
781
|
-
return -1 if !parts || parts.empty?
|
782
|
-
flags = DONTWAIT if dontwait?(flags)
|
783
|
-
|
784
|
-
parts[0..-2].each do |part|
|
785
|
-
rc = send_string part, (flags | ZMQ::SNDMORE)
|
786
|
-
return rc unless Util.resultcode_ok?(rc)
|
787
|
-
end
|
788
|
-
|
789
|
-
send_string parts[-1], flags
|
790
|
-
end
|
791
|
-
|
792
|
-
# Send a sequence of messages as a multipart message out of the +parts+
|
793
|
-
# passed in for transmission. Every element of +parts+ should be
|
794
|
-
# a Message (or subclass).
|
795
|
-
#
|
796
|
-
# +flags+ may be ZMQ::DONTWAIT.
|
797
|
-
#
|
798
|
-
# Returns 0 when the messages were successfully enqueued.
|
799
|
-
# Returns -1 under two conditions.
|
800
|
-
# 1. A message could not be enqueued
|
801
|
-
# 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
|
802
|
-
#
|
803
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
804
|
-
# cause.
|
805
|
-
#
|
806
|
-
def sendmsgs parts, flags = 0
|
807
|
-
return -1 if !parts || parts.empty?
|
808
|
-
flags = DONTWAIT if dontwait?(flags)
|
809
|
-
|
810
|
-
parts[0..-2].each do |part|
|
811
|
-
rc = sendmsg part, (flags | ZMQ::SNDMORE)
|
812
|
-
return rc unless Util.resultcode_ok?(rc)
|
813
|
-
end
|
814
|
-
|
815
|
-
sendmsg parts[-1], flags
|
816
|
-
end
|
817
|
-
|
818
|
-
# Sends a message. This will automatically close the +message+ for both successful
|
819
|
-
# and failed sends.
|
820
|
-
#
|
821
|
-
# Returns 0 when the message was successfully enqueued.
|
822
|
-
# Returns -1 under two conditions.
|
823
|
-
# 1. The message could not be enqueued
|
824
|
-
# 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
|
825
|
-
#
|
826
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
827
|
-
# cause.
|
828
|
-
#
|
829
|
-
def send_and_close message, flags = 0
|
830
|
-
rc = sendmsg message, flags
|
831
|
-
message.close
|
832
|
-
rc
|
833
|
-
end
|
834
|
-
|
835
|
-
# Dequeues a message from the underlying queue. By default, this is a blocking operation.
|
836
|
-
#
|
837
|
-
# +flags+ may take two values:
|
838
|
-
# 0 (default) - blocking operation
|
839
|
-
# ZMQ::DONTWAIT - non-blocking operation
|
840
|
-
#
|
841
|
-
# Returns 0 when the message was successfully dequeued.
|
842
|
-
# Returns -1 under two conditions.
|
843
|
-
# 1. The message could not be dequeued
|
844
|
-
# 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
|
845
|
-
#
|
846
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
847
|
-
# cause.
|
711
|
+
|
712
|
+
# Version3 only
|
848
713
|
#
|
849
|
-
#
|
850
|
-
# when #recv returns an error code.
|
714
|
+
# Disconnect the socket from the given +endpoint+.
|
851
715
|
#
|
852
|
-
def
|
853
|
-
LibZMQ.
|
716
|
+
def disconnect(endpoint)
|
717
|
+
LibZMQ.zmq_disconnect(endpoint)
|
854
718
|
end
|
855
|
-
|
856
|
-
#
|
857
|
-
# to a string.
|
858
|
-
#
|
859
|
-
# +flags+ may be ZMQ::DONTWAIT.
|
860
|
-
#
|
861
|
-
# Returns 0 when the message was successfully dequeued.
|
862
|
-
# Returns -1 under two conditions.
|
863
|
-
# 1. The message could not be dequeued
|
864
|
-
# 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
|
865
|
-
#
|
866
|
-
# With a -1 return code, the user must check ZMQ.errno to determine the
|
867
|
-
# cause.
|
719
|
+
|
720
|
+
# Version3 only
|
868
721
|
#
|
869
|
-
#
|
870
|
-
# when #recv returns an error code.
|
722
|
+
# Unbind the socket from the given +endpoint+.
|
871
723
|
#
|
872
|
-
def
|
873
|
-
|
874
|
-
rc = recvmsg message, flags
|
875
|
-
string.replace(message.copy_out_string) if Util.resultcode_ok?(rc)
|
876
|
-
message.close
|
877
|
-
rc
|
724
|
+
def unbind(endpoint)
|
725
|
+
LibZMQ.zmq_unbind(endpoint)
|
878
726
|
end
|
879
727
|
|
880
|
-
# Receive a multipart message as a list of strings.
|
881
|
-
#
|
882
|
-
# +flag+ may be ZMQ::DONTWAIT. Any other flag will be
|
883
|
-
# removed.
|
884
|
-
#
|
885
|
-
def recv_strings list, flag = 0
|
886
|
-
array = []
|
887
|
-
rc = recvmsgs array, flag
|
888
|
-
|
889
|
-
if Util.resultcode_ok?(rc)
|
890
|
-
array.each do |message|
|
891
|
-
list << message.copy_out_string
|
892
|
-
message.close
|
893
|
-
end
|
894
|
-
end
|
895
|
-
|
896
|
-
rc
|
897
|
-
end
|
898
728
|
|
899
|
-
|
900
|
-
# (by default these are instances of Message).
|
901
|
-
#
|
902
|
-
# +flag+ may be ZMQ::DONTWAIT. Any other flag will be
|
903
|
-
# removed.
|
904
|
-
#
|
905
|
-
def recvmsgs list, flag = 0
|
906
|
-
flag = DONTWAIT if dontwait?(flag)
|
907
|
-
|
908
|
-
message = @receiver_klass.new
|
909
|
-
rc = recvmsg message, flag
|
910
|
-
|
911
|
-
if Util.resultcode_ok?(rc)
|
912
|
-
list << message
|
913
|
-
|
914
|
-
# check rc *first*; necessary because the call to #more_parts? can reset
|
915
|
-
# the zmq_errno to a weird value, so the zmq_errno that was set on the
|
916
|
-
# call to #recv gets lost
|
917
|
-
while Util.resultcode_ok?(rc) && more_parts?
|
918
|
-
message = @receiver_klass.new
|
919
|
-
rc = recvmsg message, flag
|
920
|
-
|
921
|
-
if Util.resultcode_ok?(rc)
|
922
|
-
list << message
|
923
|
-
else
|
924
|
-
message.close
|
925
|
-
list.each { |msg| msg.close }
|
926
|
-
list.clear
|
927
|
-
end
|
928
|
-
end
|
929
|
-
else
|
930
|
-
message.close
|
931
|
-
end
|
729
|
+
private
|
932
730
|
|
933
|
-
|
731
|
+
def __sendmsg__(socket, address, flags)
|
732
|
+
LibZMQ.zmq_sendmsg(socket, address, flags)
|
934
733
|
end
|
935
734
|
|
936
|
-
|
937
|
-
|
938
|
-
# for receiving the message parts comprising the 0mq routing information.
|
939
|
-
#
|
940
|
-
def recv_multipart list, routing_envelope, flag = 0
|
941
|
-
parts = []
|
942
|
-
rc = recvmsgs parts, flag
|
943
|
-
|
944
|
-
if Util.resultcode_ok?(rc)
|
945
|
-
routing = true
|
946
|
-
parts.each do |part|
|
947
|
-
if routing
|
948
|
-
routing_envelope << part
|
949
|
-
routing = part.size > 0
|
950
|
-
else
|
951
|
-
list << part
|
952
|
-
end
|
953
|
-
end
|
954
|
-
end
|
955
|
-
|
956
|
-
rc
|
735
|
+
def __recvmsg__(socket, address, flags)
|
736
|
+
LibZMQ.zmq_recvmsg(socket, address, flags)
|
957
737
|
end
|
958
738
|
|
739
|
+
def populate_option_lookup
|
740
|
+
super()
|
959
741
|
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
742
|
+
# integer options
|
743
|
+
[RECONNECT_IVL_MAX, RCVHWM, SNDHWM, RATE, RECOVERY_IVL, SNDBUF, RCVBUF, IPV4ONLY,
|
744
|
+
ROUTER_BEHAVIOR, TCP_KEEPALIVE, TCP_KEEPALIVE_CNT,
|
745
|
+
TCP_KEEPALIVE_IDLE, TCP_KEEPALIVE_INTVL, TCP_ACCEPT_FILTER].each { |option| @option_lookup[option] = 0 }
|
746
|
+
|
747
|
+
# long long options
|
748
|
+
[MAXMSGSIZE].each { |option| @option_lookup[option] = 1 }
|
964
749
|
end
|
965
|
-
alias :noblock? :dontwait?
|
966
|
-
|
967
|
-
def int_option? name
|
968
|
-
super(name) ||
|
969
|
-
RECONNECT_IVL_MAX == name ||
|
970
|
-
RCVHWM == name ||
|
971
|
-
SNDHWM == name ||
|
972
|
-
RATE == name ||
|
973
|
-
RECOVERY_IVL == name ||
|
974
|
-
SNDBUF == name ||
|
975
|
-
RCVBUF == name
|
976
|
-
end
|
977
|
-
|
978
|
-
def populate_option_lookup
|
979
|
-
super()
|
980
|
-
|
981
|
-
# integer options
|
982
|
-
[RECONNECT_IVL_MAX, RCVHWM, SNDHWM, RATE, RECOVERY_IVL, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 0 }
|
983
|
-
end
|
984
750
|
|
985
751
|
# these finalizer-related methods cannot live in the CommonSocketBehavior
|
986
752
|
# module; they *must* be in the class definition directly
|