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
Printing Elements of Array Using Erb
Need Help Maximizing 3 Factors in Multiple, Similar Objects and Ordering Appropriately
Ruby Tcpsocket: Find Out How Much Data Is Available
Detecting Overlapping Ranges in Ruby
Trying to Set Up Amazon's S3 Bucket: 403 Forbidden Error & Setting Permissions
How to Split a String into Consecutive Substrings of Length at Most 3 in All Possible Ways
How to Search Array Through Ransack Gem
Grouped Collection Select Alphabetical Order Rails
How to Deal with App_Key and App_Secret (Dropbox API)
Listing Directories at a Given Level in Amazon S3
Installing Libyaml for Ruby on a MAC Osx (Lion)
Ruby -V Dyld: Library Not Loaded: /Usr/Local/Lib/Libgmp.10.Dylib
Is It a Good Idea to Purge Old Rails Migration Files
Rails 3.2.8 - How to Get the Week Number from Rails