Class: NNG::Socket

Inherits:
Object
  • Object
show all
Defined in:
lib/nng/socket.rb

Overview

High-level socket interface

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(protocol, raw: false) ⇒ Socket

Create a new socket

Parameters:

  • protocol (Symbol)

    protocol name (:pair0, :pair1, :push, :pull, :pub, :sub, :req, :rep, :surveyor, :respondent, :bus)

  • raw (Boolean) (defaults to: false)

    open in raw mode



13
14
15
16
# File 'lib/nng/socket.rb', line 13

def initialize(protocol, raw: false)
  @socket = Protocols.open_socket(protocol, raw: raw)
  @closed = false
end

Instance Attribute Details

#socketObject (readonly)

Returns the value of attribute socket.



8
9
10
# File 'lib/nng/socket.rb', line 8

def socket
  @socket
end

Instance Method Details

#closenil

Close the socket

Returns:

  • (nil)


177
178
179
180
181
182
# File 'lib/nng/socket.rb', line 177

def close
  return if @closed
  FFI.nng_close(@socket)
  @closed = true
  nil
end

#closed?Boolean

Check if socket is closed

Returns:

  • (Boolean)


186
187
188
# File 'lib/nng/socket.rb', line 186

def closed?
  @closed
end

#dial(url, flags: 0) ⇒ self

Dial (connect) to an address

Parameters:

  • url (String)

    URL to connect to (e.g., “tcp://127.0.0.1:5555”)

  • flags (Integer) (defaults to: 0)

    optional flags

Returns:

  • (self)


33
34
35
36
37
38
# File 'lib/nng/socket.rb', line 33

def dial(url, flags: 0)
  check_closed
  ret = FFI.nng_dial(@socket, url, nil, flags)
  FFI.check_error(ret, "Dial to #{url}")
  self
end

#get_option(name, type: :int) ⇒ Object

Get socket option

Parameters:

  • name (String)

    option name

  • type (Symbol) (defaults to: :int)

    expected type (:bool, :int, :size, :uint64, :string, :ms)

Returns:

  • (Object)

    option value



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/nng/socket.rb', line 108

def get_option(name, type: :int)
  check_closed

  # :ms is actually :int32 (nng_duration)
  ptr_type = type == :ms ? :int32 : type
  value_ptr = ::FFI::MemoryPointer.new(ptr_type)

  ret = case type
        when :bool
          FFI.nng_getopt_bool(@socket, name, value_ptr)
        when :int
          FFI.nng_getopt_int(@socket, name, value_ptr)
        when :size
          FFI.nng_getopt_size(@socket, name, value_ptr)
        when :uint64
          FFI.nng_getopt_uint64(@socket, name, value_ptr)
        when :ms
          FFI.nng_getopt_ms(@socket, name, value_ptr)
        when :string
          FFI.nng_getopt_string(@socket, name, value_ptr)
        else
          raise ArgumentError, "Unknown option type: #{type}"
        end

  FFI.check_error(ret, "Get option #{name}")

  if type == :string
    str_ptr = value_ptr.read_pointer
    result = str_ptr.read_string
    FFI.nng_strfree(str_ptr)
    result
  else
    value_ptr.read(ptr_type)
  end
end

#idInteger

Get socket ID

Returns:

  • (Integer)

    socket ID



171
172
173
# File 'lib/nng/socket.rb', line 171

def id
  FFI.nng_socket_id(@socket)
end

#listen(url, flags: 0) ⇒ self

Listen on an address

Parameters:

  • url (String)

    URL to listen on (e.g., “tcp://0.0.0.0:5555”, “ipc:///tmp/test.sock”)

  • flags (Integer) (defaults to: 0)

    optional flags

Returns:

  • (self)


22
23
24
25
26
27
# File 'lib/nng/socket.rb', line 22

def listen(url, flags: 0)
  check_closed
  ret = FFI.nng_listen(@socket, url, nil, flags)
  FFI.check_error(ret, "Listen on #{url}")
  self
end

#recv(flags: FFI::NNG_FLAG_ALLOC) ⇒ String

Receive data

Parameters:

  • flags (Integer) (defaults to: FFI::NNG_FLAG_ALLOC)

    optional flags (e.g., FFI::NNG_FLAG_NONBLOCK)

Returns:

  • (String)

    received data



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/nng/socket.rb', line 58

def recv(flags: FFI::NNG_FLAG_ALLOC)
  check_closed

  buf_ptr = ::FFI::MemoryPointer.new(:pointer)
  size_ptr = ::FFI::MemoryPointer.new(:size_t)

  ret = FFI.nng_recv(@socket, buf_ptr, size_ptr, flags)
  FFI.check_error(ret, "Receive data")

  # Read the data
  response_buf = buf_ptr.read_pointer
  response_size = size_ptr.read(:size_t)
  data = response_buf.read_bytes(response_size)

  # Free NNG-allocated memory
  FFI.nng_free(response_buf, response_size)

  data
end

#recv_timeout=(ms) ⇒ self

Set receive timeout

Parameters:

  • ms (Integer)

    timeout in milliseconds

Returns:

  • (self)


154
155
156
# File 'lib/nng/socket.rb', line 154

def recv_timeout=(ms)
  set_option_ms('recv-timeout', ms)
end

#send(data, flags: 0) ⇒ self

Send data

Parameters:

  • data (String)

    data to send

  • flags (Integer) (defaults to: 0)

    optional flags (e.g., FFI::NNG_FLAG_NONBLOCK)

Returns:

  • (self)


44
45
46
47
48
49
50
51
52
53
# File 'lib/nng/socket.rb', line 44

def send(data, flags: 0)
  check_closed
  data_str = data.to_s
  data_ptr = ::FFI::MemoryPointer.new(:uint8, data_str.bytesize)
  data_ptr.put_bytes(0, data_str)

  ret = FFI.nng_send(@socket, data_ptr, data_str.bytesize, flags)
  FFI.check_error(ret, "Send data")
  self
end

#send_timeout=(ms) ⇒ self

Set send timeout

Parameters:

  • ms (Integer)

    timeout in milliseconds

Returns:

  • (self)


147
148
149
# File 'lib/nng/socket.rb', line 147

def send_timeout=(ms)
  set_option_ms('send-timeout', ms)
end

#set_option(name, value) ⇒ self

Set socket option

Parameters:

  • name (String)

    option name

  • value (Object)

    option value

Returns:

  • (self)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/nng/socket.rb', line 82

def set_option(name, value)
  check_closed

  case value
  when true, false
    ret = FFI.nng_setopt_bool(@socket, name, value)
  when Integer
    if value >= 0 && value <= 2**31 - 1
      ret = FFI.nng_setopt_int(@socket, name, value)
    else
      ret = FFI.nng_setopt_uint64(@socket, name, value)
    end
  when String
    ret = FFI.nng_setopt_string(@socket, name, value)
  else
    raise ArgumentError, "Unsupported option value type: #{value.class}"
  end

  FFI.check_error(ret, "Set option #{name}")
  self
end

#set_option_ms(name, ms) ⇒ self

Set timeout option

Parameters:

  • name (String)

    option name

  • ms (Integer)

    timeout in milliseconds

Returns:

  • (self)


162
163
164
165
166
167
# File 'lib/nng/socket.rb', line 162

def set_option_ms(name, ms)
  check_closed
  ret = FFI.nng_setopt_ms(@socket, name, ms)
  FFI.check_error(ret, "Set option #{name}")
  self
end