From: Eric Wong Date: 2011-09-08T02:50:12+09:00 Subject: Re: TCPSocket recv's nil with gets() if the server crashes? "Bill W." wrote: > using gets() from a TCPSocket seems to be a common question, since > everyone seems to have the problem where it hangs if the socket isn't > closed by the server. (I do find this odd, is it actually expected you > know every time how many lines the server will send back?) It depends on the protocol. > Is there a more efficient or accepted way to read an unknown amount of > data from a socket than the way I am doing it? If it's something important, then use IO#readpartial and provide your own buffering/parsing. If a robust library already exists for whatever you're reading, use that. The problem with IO#gets is that it can still hang indefinitely if the server sent an incomplete line. select() will wake up from one byte of data, but the server could've had its connection truncated before the rest of the line reached you. The Net::* libraries in the Ruby standard library implement their own line-buffering for this reason. > I've seen it done with 'timeout' and catches the error, but select() > includes a timeout. timeout will protect you from the incomplete line case when using (much of) the Ruby standard library. It's unreliable with some 3rd-party extensions and a bit hackish, though. > I've seen things about sync and flush on the client side, but since I > have not once seen any comment from the asker that it actually worked, > I've never checked into it. Ruby (at least MRI) sockets default to IO#sync=true so in many cases you don't need to flush. -- Eric Wong