Class: TCPTimeout::TCPSocket
- Inherits:
-
Object
- Object
- TCPTimeout::TCPSocket
- Defined in:
- lib/tcp_timeout.rb
Instance Method Summary collapse
- #connect ⇒ Object
-
#initialize(host, port, opts = {}) ⇒ TCPSocket
constructor
A new instance of TCPSocket.
- #read(length = nil, *args) ⇒ Object
- #readbyte ⇒ Object
- #readpartial(length, *args) ⇒ Object
- #write(data, timeout = nil) ⇒ Object
Constructor Details
#initialize(host, port, opts = {}) ⇒ TCPSocket
Returns a new instance of TCPSocket.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/tcp_timeout.rb', line 25 def initialize(host, port, opts = {}) @connect_timeout = opts[:connect_timeout] @write_timeout = opts[:write_timeout] @read_timeout = opts[:read_timeout] family = opts[:family] || Socket::AF_INET address = Socket.getaddrinfo(host, nil, family).first[3] @sockaddr = Socket.pack_sockaddr_in(port, address) @socket = Socket.new(family, Socket::SOCK_STREAM, 0) @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) local_host = opts[:local_host] local_port = opts[:local_port] if local_host || local_port local_host ||= '' local_address = Socket.getaddrinfo(local_host, nil, family).first[3] local_sockaddr = Socket.pack_sockaddr_in(local_port, local_address) @socket.bind(local_sockaddr) end connect end |
Instance Method Details
#connect ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/tcp_timeout.rb', line 49 def connect return @socket.connect(@sockaddr) unless @connect_timeout begin @socket.connect_nonblock(@sockaddr) rescue Errno::EINPROGRESS select_timeout(:connect, @connect_timeout) # If there was a failure this will raise an Error begin @socket.connect_nonblock(@sockaddr) rescue Errno::EISCONN # Successfully connected end end end |
#read(length = nil, *args) ⇒ Object
86 87 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 |
# File 'lib/tcp_timeout.rb', line 86 def read(length = nil, *args) raise ArgumentError, 'too many arguments' if args.length > 2 timeout = (args.length > 1) ? args.pop : @read_timeout return @socket.read(length, *args) unless length > 0 && timeout buffer = args.first || ''.force_encoding(Encoding::ASCII_8BIT) begin # Drain internal buffers @socket.read_nonblock(length, buffer) return buffer if buffer.bytesize >= length rescue Errno::EWOULDBLOCK # Internal buffers were empty buffer.clear rescue EOFError return nil end @chunk ||= ''.force_encoding(Encoding::ASCII_8BIT) loop do timeout = select_timeout(:read, timeout) begin @socket.read_nonblock(length, @chunk) rescue Errno::EWOULDBLOCK retry rescue EOFError return buffer.empty? ? nil : buffer end buffer << @chunk if length length -= @chunk.bytesize return buffer if length <= 0 end end end |
#readbyte ⇒ Object
140 141 142 |
# File 'lib/tcp_timeout.rb', line 140 def readbyte readpartial(1).ord end |
#readpartial(length, *args) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/tcp_timeout.rb', line 126 def readpartial(length, *args) raise ArgumentError, 'too many arguments' if args.length > 2 timeout = (args.length > 1) ? args.pop : @read_timeout return @socket.readpartial(length, *args) unless length > 0 && timeout begin @socket.read_nonblock(length, *args) rescue Errno::EWOULDBLOCK timeout = select_timeout(:read, timeout) retry end end |
#write(data, timeout = nil) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/tcp_timeout.rb', line 65 def write(data, timeout = nil) timeout ||= @write_timeout return @socket.write(data) unless timeout length = data.bytesize total_count = 0 loop do begin count = @socket.write_nonblock(data) rescue Errno::EWOULDBLOCK timeout = select_timeout(:write, timeout) retry end total_count += count return total_count if total_count >= length data = data.byteslice(count..-1) end end |