Search code examples
rubytcpconnectiontcpservertcpsocket

Read data both ways TCPServer Ruby


im new in Ruby and Im trying to set up a TCPServer and a Client, but Im having trouble getting the data from the client to the server because for some reason when the client connects, the connection is freezed inside the while loop. Here is the code:

server.rb

require "socket"
server = TCPServer.new 1234
test = ""

loop do
  session = server.accept
  puts "Entering enter code herewhile loop."
  while line = session.gets
    puts "Inside while loop"
    test << line
  end
    puts "Finished reading data"

    puts "Data recieved - #{test}" # Read data from client
    session.write "Time is #{Time.now}" # Send data to clent
    session.close
end

client.rb

require "socket"

socket = TCPSocket.open("localhost", 1234)
socket.puts "Sending data.." # Send data to server
while(line = socket.gets)
  puts line
end # Print sever response
socket.close

The server prints "Inside while loop" one time, and then for some reason it never prints "Finished reading data" until I manually end the client connection, after the client ends the connection the server prints everything OK. How can I make this code work? Thanks!


Solution

  • IO#gets is a blocking call. It waits for either a new line from the underlying I/O stream, or the end of the stream. (in which case it returns nil)

    In server.rb you have

    while line = session.gets
      puts "Inside while loop"
      test << line
    end
    

    session.gets reads one line from your client, prints some debug info and appends the line to test. It then attempts to read another line from the client.

    Your client.rb however never sends a seconds line, nor does it close the stream. It sends a single line:

    socket.puts "Sending data.." # Send data to server
    

    and then waits for a response:

    while(line = socket.gets)
      puts line
    end
    

    which never comes because the server is sitting in the while loop, waiting for more data from the client.

    You can solve this by calling close_write after all data has been sent:

    socket.puts "Sending data.." # Send data to server
    socket.close_write           # Close socket for further writing
    

    Calling close_write instead of close allows you to still read from the socket. It will also cause the server's session.gets to return nil, so it can get out of its loop.