"Bill W." <sirwillard42 / gmail.com> 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