1

I am following the tutorial: http://www.tutorialspoint.com/ruby/ruby_socket_programming.htm and using it to set up the "Simple Client".

The code is as follows:

    require 'socket'      # Sockets are in standard library

    hostname = 'localhost'
    port = 2000

    s = TCPSocket.open(host, port)

    while line = s.gets   # Read lines from the socket
      puts line.chop      # And print with platform line terminator
    end
    s.close               # Close the socket when done

When I execute a single s.gets statement, I get the first response line from the server. When I do s.gets again, I get the second response line, etc. However, the moment I get to the end of the response and do s.gets then the program goes into a frozen state. (This is if I test the above program from the Rails Console). The same happens when I run the code - the freeze occurs when the while statement does the final s.gets. Any ideas on how to solve this?

For information: The server is a C# server that sends response messages using the following C# code (each line of the response uses the same code and the final line in the response is not treated any differently from the other lines):

    socket.Send(Encoding.ASCII.GetBytes(msg + "\r\n"));

So I am thinking the client freezes because it probably doesn't interpret the servers "end of response" properly. Any ideas?

Stanley
  • 5,261
  • 9
  • 38
  • 55

4 Answers4

2

It seems like there is a problem with reading the nil value from the socket. Still not sure why this happens, but using a selector as suggested in Recovering from a broken TCP socket in Ruby when in gets() solves the problem very nicely (would have upvoted his answer, but don't have enough rep).

Solution I followed was to add the selector in a method as follows:

    def next_line_readable?(socket)
      readfds, writefds, exceptfds = select([socket], nil, nil, 0.1)
      p :r => readfds, :w => writefds, :e => exceptfds
      readfds #Will be nil if next line cannot be read
    end

and then in main program to use it like:

    socket = TCPSocket.open(host, port)
    while next_line_readable?(socket)
      puts socket.gets.chop
    end
Community
  • 1
  • 1
Stanley
  • 5,261
  • 9
  • 38
  • 55
  • The solution I use for my socket apps it to call `socket.recvfrom` and then iterate over the message by either `each_byte` or `each_line` depending on the data I'm receiving. Functionally similar, its just that I have to use lower lever functions to maintain non-blocking IO for my app. – badams Jun 07 '12 at 15:07
1

Try this am writing a tcp client and server in ruby

def sendto(str)
  begin
     socket.write(str)
    puts "Sent Message to:" +  socket.peeraddr[2]
  rescue Exception=>e
    puts red("Error Make sure the target is connected")
  end
end

Check it out works perfectly until 4hours then disconnects Connection to ruby based server

Community
  • 1
  • 1
user1692494
  • 65
  • 1
  • 7
0

Try using the socket.read or socket.recvfrom methods instead of socket.gets.

Is it the same behavior?

badams
  • 252
  • 3
  • 14
  • Exactly the same happens. If, from the console I do socket.read then it freezes immediately. When doing socket.recvfrom it returns the server response, but the moment I call it again or call it in a while loop then it also freezes. – Stanley Jun 07 '12 at 06:31
0

use recv instead of gets

   server = TCPServer.new 53492 # Server bound to port 53492
    loop do
      client = server.accept
      ansiString = client.recv(100).chomp
      client.puts result
      client.close
     end

you can convert it into the thread also as:

   server = TCPServer.new 53492 # Server bound to port 53492
   Thread.start(server.accept) do |client|
      loop do
        client = server.accept
        ansiString = client.recv(100).chomp
        client.puts result
        client.close
      end
    end
vidur punj
  • 5,019
  • 4
  • 46
  • 65