Class: Ionian::Socket
- Inherits:
-
Object
- Object
- Ionian::Socket
- Defined in:
- lib/ionian/socket.rb
Overview
A convenient wrapper for TCP, UDP, and Unix client sockets.
Instance Attribute Summary collapse
-
#bind_port ⇒ Object
readonly
Local port number.
-
#host ⇒ Object
readonly
IP address or URL of server.
-
#port ⇒ Object
readonly
Remote port number.
-
#protocol ⇒ Object
(also: #protocol?)
readonly
Returns a symbol of the type of protocol this socket uses: :tcp, :udp, :unix.
Class Method Summary collapse
-
.create_broadcast_socket(**kwargs) ⇒ Ionian::Socket
A broadcast socket.
Instance Method Summary collapse
-
#closed? ⇒ Boolean
Returns true if the socket is closed.
-
#cmd(data, **kwargs) {|match| ... } ⇒ Array<MatchData>
Send a command (data) to the socket.
-
#expression ⇒ Regexp
The regular expression used to match incoming data.
-
#expression=(exp) ⇒ Object
Set the regular expression used to match incoming data.
-
#fd ⇒ IO
The file descriptor for this socket.
-
#flush ⇒ Object
Flushes buffered data to the operating system.
-
#has_data?(**kwargs) ⇒ Boolean
data until giving up.
-
#initialize(existing_socket = nil, **kwargs) {|socket| ... } ⇒ Socket
constructor
Creates a new socket or wraps an existing socket.
-
#persistent? ⇒ Boolean
True if the socket remains open after writing data.
-
#puts(*string) ⇒ Object
Writes the given string(s) to the socket and appends a newline character to any string not already ending with one.
-
#register_error_handler {|Exception, self| ... } ⇒ Block
(also: #on_error)
Register a block to be called when Extension::IO#run_match raises an error.
-
#register_match_handler {|MatchData, self| ... } ⇒ Block
(also: #on_match)
Register a block to be called when Extension::IO#run_match receives matched data.
-
#register_observer(&block) ⇒ Object
deprecated
Deprecated.
Use #register_match_handler instead.
-
#unregister_error_handler(&block) ⇒ Object
Unregister a block from being called when a IO#run_match error is raised.
-
#unregister_match_handler(&block) ⇒ Object
Unregister a block from being called when matched data is received.
-
#unregister_observer(&block) ⇒ Object
deprecated
Deprecated.
Use #unregister_match_handler instead.
-
#write(string) ⇒ Fixnum
(also: #<<)
Writes the given string to the socket.
Constructor Details
#initialize(existing_socket = nil, **kwargs) {|socket| ... } ⇒ Socket
Creates a new socket or wraps an existing socket.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/ionian/socket.rb', line 88 def initialize existing_socket = nil, **kwargs, &block @socket = existing_socket @ionian_match_handlers = [] @ionian_error_handlers = [] @expression = kwargs.fetch :expression, nil if existing_socket # Convert existing socket. @socket.extend Ionian::Extension::IO @socket.extend Ionian::Extension::Socket if existing_socket.is_a? UNIXSocket @host = existing_socket.path @port = nil else @host = existing_socket.remote_address.ip_address if existing_socket @port = existing_socket.remote_address.ip_port if existing_socket end if @socket.is_a? TCPSocket @protocol = :tcp elsif @socket.is_a? UDPSocket @protocol = :udp elsif @socket.is_a? UNIXSocket @protocol = :unix end @persistent = true # Existing sockets are always persistent. @socket.expression = @expression if @expression initialize_socket_methods else # Initialize new socket. # Parse host out of "host:port" if specified. host_port_array = kwargs.fetch(:host).to_s.split ':' @host = host_port_array[0] @port = kwargs.fetch :port, (host_port_array[1] || 23).to_i @bind_port = kwargs.fetch :bind_port, @port @connect_timeout = kwargs.fetch :connect_timeout, nil @broadcast = kwargs.fetch :broadcast, false # Automatically select UDP for the multicast range. Otherwise default to TCP. default_protocol = :tcp default_protocol = :udp if Ionian::Extension::Socket.multicast? @host default_protocol = :unix if @host.start_with? '/' default_protocol = :udp if @broadcast @protocol = kwargs.fetch :protocol, default_protocol @persistent = kwargs.fetch :persistent, true @persistent = true if @protocol == :udp @reuse_addr = kwargs.fetch :reuse_addr, false @cork = kwargs.fetch :cork, false @no_delay = kwargs.fetch :no_delay, @persistent ? false : true # Default to false for persistent sockets, true for # nonpersistent sockets. When nonpersistent, the socket # should remain open to send data in the buffer after # close is called (typically right after write). # @linger = kwargs.fetch :linger, @persistent ? false : true # TODO: For some reason linger = true is causing tests to fail. @linger = kwargs.fetch :linger, false create_socket if @persistent end if block block.call self unless self.closed? self.flush self.close end end end |
Instance Attribute Details
#bind_port ⇒ Object (readonly)
Local port number.
16 17 18 |
# File 'lib/ionian/socket.rb', line 16 def bind_port @bind_port end |
#host ⇒ Object (readonly)
IP address or URL of server.
10 11 12 |
# File 'lib/ionian/socket.rb', line 10 def host @host end |
#port ⇒ Object (readonly)
Remote port number.
13 14 15 |
# File 'lib/ionian/socket.rb', line 13 def port @port end |
#protocol ⇒ Object (readonly) Also known as: protocol?
Returns a symbol of the type of protocol this socket uses: :tcp, :udp, :unix
20 21 22 |
# File 'lib/ionian/socket.rb', line 20 def protocol @protocol end |
Class Method Details
.create_broadcast_socket(**kwargs) ⇒ Ionian::Socket
Returns a broadcast socket.
29 30 31 32 33 |
# File 'lib/ionian/socket.rb', line 29 def self.create_broadcast_socket **kwargs kwargs[:host] = kwargs.delete(:address) || '255.255.255.255' kwargs[:broadcast] = true new **kwargs end |
Instance Method Details
#closed? ⇒ Boolean
Returns true if the socket is closed.
280 281 282 283 |
# File 'lib/ionian/socket.rb', line 280 def closed? return true unless @socket @socket.closed? end |
#cmd(data, **kwargs) {|match| ... } ⇒ Array<MatchData>
Send a command (data) to the socket.
204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/ionian/socket.rb', line 204 def cmd data, **kwargs, &block create_socket unless @persistent write data @socket.flush matches = @socket.read_match(kwargs) { |match| yield match if block_given? } @socket.close unless @persistent matches end |
#expression ⇒ Regexp
Returns the regular expression used to match incoming data.
178 179 180 |
# File 'lib/ionian/socket.rb', line 178 def expression @expression || @socket.expression end |
#expression=(exp) ⇒ Object
Set the regular expression used to match incoming data.
185 186 187 188 |
# File 'lib/ionian/socket.rb', line 185 def expression= exp @expression = exp @socket.expression = exp if @socket end |
#fd ⇒ IO
Returns the file descriptor for this socket. For use with methods like IO.select.
173 174 175 |
# File 'lib/ionian/socket.rb', line 173 def fd @socket end |
#flush ⇒ Object
Flushes buffered data to the operating system. This method has no effect on non-persistent sockets.
287 288 289 |
# File 'lib/ionian/socket.rb', line 287 def flush @socket.flush if @persistent end |
#has_data?(**kwargs) ⇒ Boolean
data until giving up. Set to nil for blocking.
274 275 276 277 |
# File 'lib/ionian/socket.rb', line 274 def has_data? **kwargs return false unless @socket @socket.has_data? kwargs end |
#persistent? ⇒ Boolean
Returns True if the socket remains open after writing data.
191 192 193 |
# File 'lib/ionian/socket.rb', line 191 def persistent? @persistent == false || @persistent == nil ? false : true end |
#puts(*string) ⇒ Object
Writes the given string(s) to the socket and appends a newline character to any string not already ending with one.
293 294 295 |
# File 'lib/ionian/socket.rb', line 293 def puts *string self.write string.map{ |s| s.chomp }.join("\n") + "\n" end |
#register_error_handler {|Exception, self| ... } ⇒ Block Also known as: on_error
Register a block to be called when Extension::IO#run_match raises an error. Method callbacks can be registered with &object.method(:method).
253 254 255 256 257 |
# File 'lib/ionian/socket.rb', line 253 def register_error_handler &block @ionian_error_handlers << block unless @ionian_error_handlers.include? block @socket.register_error_handler &block if @socket block end |
#register_match_handler {|MatchData, self| ... } ⇒ Block Also known as: on_match
Register a block to be called when Extension::IO#run_match receives matched data. Method callbacks can be registered with &object.method(:method).
221 222 223 224 225 |
# File 'lib/ionian/socket.rb', line 221 def register_match_handler &block @ionian_match_handlers << block unless @ionian_match_handlers.include? block @socket.register_match_handler &block if @socket block end |
#register_observer(&block) ⇒ Object
Use #register_match_handler instead.
230 231 232 233 |
# File 'lib/ionian/socket.rb', line 230 def register_observer &block STDOUT.puts "WARN: Call to deprecated method #{__method__}" register_match_handler &block end |
#unregister_error_handler(&block) ⇒ Object
Unregister a block from being called when a IO#run_match error is raised.
263 264 265 266 267 |
# File 'lib/ionian/socket.rb', line 263 def unregister_error_handler &block @ionian_error_handlers.delete_if { |o| o == block } @socket.unregister_error_handler &block if @socket block end |
#unregister_match_handler(&block) ⇒ Object
Unregister a block from being called when matched data is received.
236 237 238 239 240 |
# File 'lib/ionian/socket.rb', line 236 def unregister_match_handler &block @ionian_match_handlers.delete_if { |o| o == block } @socket.unregister_match_handler &block if @socket block end |
#unregister_observer(&block) ⇒ Object
Use #unregister_match_handler instead.
243 244 245 246 |
# File 'lib/ionian/socket.rb', line 243 def unregister_observer &block STDOUT.puts "WARN: Call to deprecated method #{__method__}" unregister_match_handler &block end |
#write(string) ⇒ Fixnum Also known as: <<
Writes the given string to the socket.
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/ionian/socket.rb', line 299 def write string create_socket unless @persistent num_bytes = 0 if @protocol == :udp num_bytes = @socket.send string, 0 else num_bytes = @socket.write string end unless @persistent @socket.flush # Read in data to prevent RST packets. # TODO: Shutdown read stream instead? @socket.read_all nonblocking: true # TODO: Sleep added so that data can be read on the receiving # end. Can this be changed to shutdown write? # Why isn't so_linger taking care of this? # sleep 0.01 @socket.close end num_bytes end |