lib/ionian/socket.rb in ionian-0.6.6 vs lib/ionian/socket.rb in ionian-0.6.7
- old
+ new
@@ -34,10 +34,12 @@
# the remote port being connected to.
# reuse_addr: Set true to enable the SO_REUSEADDR flag. Allows local address reuse.
# no_delay: Set true to enable the TCP_NODELAY flag. Disables Nagle algorithm.
# cork: Set true to enable the TCP_CORK flag. Buffers multiple writes
# into one segment.
+ # linger: Set true to enable the SO_LINGER flag. When #close is called,
+ # waits for the send buffer to empty before closing the socket.
# expression: Overrides the #read_match regular expression for received data.
def initialize existing_socket = nil, **kwargs
@socket = existing_socket
@ionian_listeners = []
@@ -89,12 +91,18 @@
@protocol = kwargs.fetch :protocol, default_protocol
@persistent = kwargs.fetch :persistent, true
@persistent = true if @protocol == :udp
@reuse_addr = kwargs.fetch :reuse_addr, false
- @no_delay = kwargs.fetch :no_delay, 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
create_socket if @persistent
end
end
@@ -120,16 +128,11 @@
# Block yields received match.
# See Ionian::Extension::IO#read_match.
def cmd string, **kwargs, &block
create_socket unless @persistent
- if @protocol == :udp
- @socket.send string, 0
- else
- @socket.write string
- end
-
+ write string
@socket.flush
matches = @socket.read_match(kwargs) { |match| yield match if block_given? }
@socket.close unless @persistent
@@ -196,14 +199,20 @@
else
num_bytes = @socket.write string
end
unless @persistent
+ @socket.flush
+
# Read in data to prevent RST packets.
- has_data = ::IO.select [@socket], nil, nil, 0
- @socket.readpartial 0xFFFF if has_data
+ # 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
@@ -219,14 +228,14 @@
case @protocol
when :tcp
@socket = ::TCPSocket.new @host, @port
@socket.extend Ionian::Extension::Socket
- @socket.expression = @expression if @expression
- @socket.no_delay = true if @no_delay
- @socket.cork = true if @cork
+ @socket.no_delay = @no_delay
+ @socket.cork = @cork
+
when :udp
@socket = ::UDPSocket.new
@socket.extend Ionian::Extension::Socket
@socket.reuse_addr = true if
@@ -238,13 +247,13 @@
@socket.ip_add_membership if Ionian::Extension::Socket.multicast? @host
when :unix
@socket = ::UNIXSocket.new @host
@socket.extend Ionian::Extension::Socket
+
end
- # TODO: Implement SO_LINGER flag for non-persistent sockets;
- # especially send-and-forget.
+ @socket.linger = @linger
@socket.expression = @expression if @expression
# Register listeners.
@ionian_listeners.each { |proc| @socket.on_match &proc }
\ No newline at end of file