Recovering from a Broken Tcp Socket in Ruby When in Gets()

Ruby on Rails TCPSocket freezes in Client Application while loop using gets

It seems like there is a problem with reading the nil value from the socket. Still not sure why this happens, but using a selector as suggested in Recovering from a broken TCP socket in Ruby when in gets() solves the problem very nicely (would have upvoted his answer, but don't have enough rep).

Solution I followed was to add the selector in a method as follows:

    def next_line_readable?(socket)
readfds, writefds, exceptfds = select([socket], nil, nil, 0.1)
p :r => readfds, :w => writefds, :e => exceptfds
readfds #Will be nil if next line cannot be read
end

and then in main program to use it like:

    socket = TCPSocket.open(host, port)
while next_line_readable?(socket)
puts socket.gets.chop
end

Ruby Socket Client hanging when calling Go RPC TCP Service

OK, so the actual fix I needed to make in my code was as follows:

The incoming args needed to be a custom type so you could export it and the fields themselves within that type need to be exported...

type Args struct {
Foo string
Bar string
}

But more importantly, on the Ruby side, you need to send your JSON in a format that makes this requirement -> https://golang.org/src/net/rpc/jsonrpc/client.go#L45 <- happy

So do this...

b = {
:method => "Compose.Details",
:params => [{ :Foo => "Foo!", :Bar => "Bar!" }],
:id => "0" # id is just echo'ed back to the client
}

How do I set the socket timeout in Ruby?

The solution I found which appears to work is to use Timeout::timeout:

require 'timeout'
...
begin
timeout(5) do
message, client_address = some_socket.recvfrom(1024)
end
rescue Timeout::Error
puts "Timed out!"
end

What does line = s.gets mean in this socket example?

The example from documentation can be explained as

Open a TCP socket to localhost, port 2000.

Read from it line by line; while reading print what was read.

When there is no content left to read, close the socket.

Basically, I think the whole expression

while line = s.gets
puts line
end

can be confusing for Ruby newcomers.

The code snippet above reads content from socket s with method gets. This method returns a "line" (a string), including trailing symbol \n. That result is assigned to line variable.

line = s.gets expression is not a comparison as it may seem; it's assignment. Every assignment in Ruby returns a value, which is assigned. So the result of this operation is a string, returned by gets.

When evaluated by while statement, string is converted to boolean. Any string, even empty one, is considered as true, so block with puts line is executed.

Since it is a while loop, it will be repeated again and again, until gets method returns nil, which means there is nothing left to read from the socket (transfer complete).



Related Topics



Leave a reply



Submit