title: Read entire message from a TCPSocket without hanging
body: <p>I'm putting together a TCPServer in Ruby 3.0.2 and I'm finding that I can't seem to read the entire packet without blocking (until the socket is closed).</p>
  <p><strong>Edit:</strong> There was some confusion on what I was trying to do - my bad - so just to help clarify: I wanted to read everything that had been sent over the TCP connection so far. (end edit)</p>
  <p>My first try was:</p>
  <pre><code>#!/snap/bin/ruby
  require 'socket'
  
  server = TCPServer.new('localhost', 4200)
  
  loop {
    Thread.start(server.accept) do |connection|
      puts connection.gets  # The important line
    end
  }
  </code></pre>
  <p>But that hangs until the client closes the connection. Okay, so I take a look at <code>connection.methods</code>, and the ruby docs and try a bunch of options that seem promising. Basically, there is two types of read methods: blocking and nonblocking.</p>
  <p>The blocking methods that I tried are <code>.read</code>, <code>.gets</code>, <code>.readlines</code>, <code>.readline</code>, <code>.recv</code>, and <code>.recvmsg</code>. Now <code>.read</code>, <code>.readlines</code>, and <code>.gets</code> all hang (until the socket is closed) - so that's not helpful. The other ones (eg. <code>.readline</code>, the <code>recv</code> methods) don't read the entire message. Now, I could read each line until I see an empty line and parse the HTTP header from there. But there's got to be a better way; I don't want to have to worry about getting a corrupted message and hanging because I didn't read an empty line at the end of the header.</p>
  <p>So I went looking at the non-blocking options. Specifically <code>.recv_nonblock</code> and <code>.recvmsg_nonblock</code>. Both of these throw errors (<em>Resource temporarily unavailable - recvfrom(2) would block</em> and <em>Resource temporarily unavailable - recvmsg(2)</em> respectively).</p>
  <p>Any ideas on what could be going on? I <em>think</em> it has something to with me using Ruby 3, because trying out the code on Ruby 2.5, <code>client.gets</code> returns a line (doesn't hang), although <code>.readlines</code> does hang - so not sure what's going on.</p>
  <p>Ideally, I could just call something along the lines of <code>client.get_message</code> and I would get the entire message that has been sent, but I'd also be okay with working at the TCP level and getting the packet size, reading that size, and reconstructing the message from there.</p>