class ZMQ::Socket

See api.zeromq.org/4-0:zmq-socket Not thread safe.

Attributes

context[R]

The socket's ZMQ::Context.

pointer[R]

The FFI pointer to the socket.

type[R]

The socket's ZeroMQ socket type (e.g. ZMQ::ROUTER).

Public Class Methods

finalizer(pointer, context, pid) click to toggle source

Create a safe finalizer for the socket pointer to close on GC

# File lib/0mq/socket.rb, line 61
def self.finalizer(pointer, context, pid)
  Proc.new do
    if Process.pid == pid
      context.send :unregister_socket_pointer, pointer
      LibZMQ.zmq_close pointer
    end
  end
end
new(type, opts={}) click to toggle source
# File lib/0mq/socket.rb, line 17
def initialize(type, opts={})
  @closed = false
  @context = opts.fetch :context, ZMQ::DefaultContext
  @type = type
  @pointer = LibZMQ.zmq_socket @context.pointer, @type
  ZMQ.error_check true if @pointer.null?
  
  @msgptr = FFI::MemoryPointer.new LibZMQ::Message.size, 1, false
  
  @context.send :register_socket_pointer, @pointer
  
  ObjectSpace.define_finalizer self,
    self.class.finalizer(@pointer, @context, Process.pid)
end

Public Instance Methods

bind(endpoint) click to toggle source

Bind to an endpoint

# File lib/0mq/socket.rb, line 76
def bind(endpoint)
  rc = LibZMQ.zmq_bind @pointer, endpoint
  ZMQ.error_check true if rc==-1
end
close() click to toggle source

Close the socket

# File lib/0mq/socket.rb, line 38
def close
  @closed = true
  
  if @pointer
    @temp_buffers.clear if @temp_buffers
    
    ObjectSpace.undefine_finalizer self
    @context.send :unregister_socket_pointer, @pointer
    
    rc = LibZMQ.zmq_close @pointer
    ZMQ.error_check true if rc==-1
    
    @pointer = nil
    @context = nil
  end
end
closed?() click to toggle source

Returns true if the socket is closed.

# File lib/0mq/socket.rb, line 56
def closed?
  @closed
end
connect(endpoint) click to toggle source

Connect to an endpoint

# File lib/0mq/socket.rb, line 82
def connect(endpoint)
  rc = LibZMQ.zmq_connect @pointer, endpoint
  ZMQ.error_check true if rc==-1
end
disconnect(endpoint) click to toggle source

Disconnect from an endpoint

# File lib/0mq/socket.rb, line 94
def disconnect(endpoint)
  rc = LibZMQ.zmq_disconnect @pointer, endpoint
  ZMQ.error_check true if rc==-1
end
get_opt(option) click to toggle source

Get a socket option

# File lib/0mq/socket.rb, line 202
def get_opt(option)
  type = @@option_types.fetch(option) \
    { raise ArgumentError, "Unknown option: #{option}" }
  
  value, size = get_opt_pointers type
  
  rc = LibZMQ.zmq_getsockopt @pointer, option, value, size
  ZMQ.error_check true if rc==-1
  
  if type == :string
    value.read_string(size.read_int-1)
  elsif type == :bool
    value.read_int == 1
  else
    value.send :"read_#{type}"
  end
end
inspect() click to toggle source

Show a useful inspect output

# File lib/0mq/socket.rb, line 33
def inspect
  "#<#{self.class}:#{type_sym}:#{object_id.to_s(16)}>"
end
recv_array(flags = 0) click to toggle source

Receive a multipart message as an array of strings

# File lib/0mq/socket.rb, line 141
def recv_array(flags = 0)
  [].tap do |ary|
    loop do
      ary << recv_string(flags)
      break unless get_opt(ZMQ::RCVMORE)
    end
  end
end
recv_string(flags = 0) click to toggle source

Receive a string from the socket

# File lib/0mq/socket.rb, line 117
def recv_string(flags = 0)
  rc = LibZMQ.zmq_msg_init @msgptr
  ZMQ.error_check true if rc==-1
  
  rc = LibZMQ.zmq_recvmsg @pointer, @msgptr, flags
  ZMQ.error_check true if rc==-1
  
  str = LibZMQ.zmq_msg_data(@msgptr)
              .read_string(LibZMQ.zmq_msg_size(@msgptr))
  
  rc = LibZMQ.zmq_msg_close @msgptr
  ZMQ.error_check true if rc==-1
  
  str
end
recv_with_routing() click to toggle source

Receive a multipart message as routing array and a body array All parts before an empty part are considered routing parts, and all parta after the empty part are considered body parts. The empty delimiter part is not included in the resulting arrays.

# File lib/0mq/socket.rb, line 162
def recv_with_routing
  [[],[]].tap do |routing, body|
    loop do
      nxt = recv_string
      break if nxt.empty?
      routing << nxt
      raise ArgumentError, "Expected empty routing delimiter in "\
                           "multipart message: #{routing}" \
                            unless get_opt ZMQ::RCVMORE
    end
    loop do
      body << recv_string
      break unless get_opt(ZMQ::RCVMORE)
    end
  end
end
send_array(array, flags = 0) click to toggle source

Send a multipart message as an array of strings

# File lib/0mq/socket.rb, line 134
def send_array(array, flags = 0)
  array = array.to_a
  array[0...-1].each { |str| send_string str, ZMQ::SNDMORE|flags }
  send_string array.last, flags
end
send_string(string, flags = 0) click to toggle source

Send a string to the socket

# File lib/0mq/socket.rb, line 100
def send_string(string, flags = 0)
  string = string.to_s
  size = string.respond_to?(:bytesize) ? string.bytesize : string.size
  @msgbuf = LibC.malloc size
  @msgbuf.write_string string, size
  
  rc = LibZMQ.zmq_msg_init_data @msgptr, @msgbuf, size, LibC::Free, nil
  ZMQ.error_check true if rc==-1
  
  rc = LibZMQ.zmq_sendmsg @pointer, @msgptr, flags
  ZMQ.error_check true if rc==-1
  
  rc = LibZMQ.zmq_msg_close @msgptr
  ZMQ.error_check true if rc==-1
end
send_with_routing(routing, body) click to toggle source

Send a multipart message as routing array and a body array All parts before an empty part are considered routing parts, and all parta after the empty part are considered body parts. The empty delimiter part should not be included in the input arrays.

# File lib/0mq/socket.rb, line 154
def send_with_routing(routing, body)
  send_array [*routing, '', *body]
end
set_opt(option, value) click to toggle source

Set a socket option

# File lib/0mq/socket.rb, line 180
def set_opt(option, value)
  type = @@option_types.fetch(option) \
    { raise ArgumentError, "Unknown option: #{option}" }
  
  unless type == :string
    if type == :bool
      valptr = FFI::MemoryPointer.new(:int)
      valptr.write_int(value ? 1 : 0)
    else
      valptr = FFI::MemoryPointer.new(type)
      valptr.send :"write_#{type}", value
    end
    value = valptr
  end
  
  rc = LibZMQ.zmq_setsockopt @pointer, option, value, value.size
  ZMQ.error_check true if rc==-1
  
  value
end
to_ptr() click to toggle source

Returns the socket's FFI pointer.

# File lib/0mq/socket.rb, line 221
def to_ptr
  @pointer
end
type_sym() click to toggle source

Get the socket type name as a symbol

# File lib/0mq/socket.rb, line 71
def type_sym
  ZMQ::SocketTypeNameMap[type].to_sym
end
unbind(endpoint) click to toggle source

Unbind from an endpoint

# File lib/0mq/socket.rb, line 88
def unbind(endpoint)
  rc = LibZMQ.zmq_unbind @pointer, endpoint
  ZMQ.error_check true if rc==-1
end

Private Instance Methods

get_opt_pointers(type) click to toggle source
# File lib/0mq/socket.rb, line 227
def get_opt_pointers(type)
  type = :int if type == :bool
  
  @temp_buffers ||= { string: [
      FFI::MemoryPointer.new(255),
      FFI::MemoryPointer.new(:size_t).write_int(255)
  ] }
  @temp_buffers[type] ||= [
    FFI::MemoryPointer.new(type),
    FFI::MemoryPointer.new(:size_t).write_int(FFI.type_size(type))
  ]
end