I have following (simplified) ruby code, which opens ruby's TCP-Socket and reads from it:
socket = TCPSocket.open(server, port)
while line = socket.gets
line = line.chop
end
Now I want read from the socket just for a given period of time (i.e. 1 minute). So after 1 one minute, the while block should be breaked and the process should exit.
Putting a line like
break if (elapsed_time > 1000)
into the gets-block is not possible, because if nothing is written to the socket, this line of code is not reached.
To read from an IO in a non-blocking way, there's
read_nonblock. It either reads the available bytes (up to a given maximum) or raise an exception if the IO isn't ready for reading. Upon rescuing the exception, you can callIO.selectto wait for the IO to become ready for reading.IO.selecttakes up to 3 arrays with IOs to be monitored for 1) reading, 2) writing and 3) exceptions (you can monitor many IOs at once). A basic loop could look like this:The above attempts to reads up to 1024 bytes which will be appended to
buffer. If the read succeeds, it will read the next 1024 bytes and so on. If a read fails because the socket doesn't have any data, it callsIO.selectwhich monitors the socket and returns as soon as more data is available.IO.selectalso takes a 4th argumenttimeout. If the given value (in seconds) is exceeded, it will returnnilwhich can be used tobreakthe loop conditionally:The above will wait up to 10 seconds for more data to become available or break the loop otherwise.
However, it will wait for 10 seconds per (failed) read attempt. To get a "global" timeout for the whole loop you might need something along these lines:
The above keeps track of the remaining time (in seconds) and passed that value as a timeout to
IO.select.Finally, you might want to process the lines as soon as they become available. To do so you could check the string buffer for a newline character and extract the line via
slice!(possibly in a loop since you might have read multiple lines at once). Each extracted line could then be yielded:Example usage: