Forum: Ruby Can't read more than one message from a socket

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Chris B. (Guest)
on 2009-01-22 00:48
I am connecting to a server and then waiting to receive messages over
the socket. For each message received I wish to then execute some code.

I have tried recv, gets, and readpartial all with no luck.

I tried something like this:

loop {
  data = socket.recv( 100 )
  puts "Line received"
  puts data
}

What I see when sending messages from the server is that the first
message is received and printed, then the program hangs for 15 secs,
then the loop starts but each time the data is empty.

I am obviously doing something really stupid but I've spend hours now on
this so if someone could hint at how to do this I would be most
grateful.

Thanks,

Chris
Eric H. (Guest)
on 2009-01-22 04:05
(Received via mailing list)
On Jan 21, 2009, at 14:46 PM, Chris B. wrote:

>  puts "Line received"
> grateful.
Since you didn't post your entire program, we can only be of limited
assistance.

This program works for me:

$ ruby -rsocket -e 'sv = TCPServer.new nil, 4000; so = sv.accept;
while data = so.read(10) do p :read => data end'
{:read=>"0123456789"}
{:read=>"\r\n234567\r\n"}
$

It has many flaws, for example it doesn't handle any error conditions,
and only responds to one connection from the server.

The output you see is from connecting with telnet:

$ telnet localhost 4000
Trying ::1...
Connected to localhost.
Escape character is '^]'.
0123456789
234567
^]
telnet> quit
Connection closed.
$
Chris B. (Guest)
on 2009-01-22 22:19
Eric H. wrote:

> $ ruby -rsocket -e 'sv = TCPServer.new nil, 4000; so = sv.accept;
> while data = so.read(10) do p :read => data end'
> {:read=>"0123456789"}
> {:read=>"\r\n234567\r\n"}
> $
>


Thanks for the help. I used your structure (while data = socket.read) as
follows in my client app (after opening the in_socket to the server):

messageCount = 0
while data = in_socket.recv( 100 )
  if data.size > 0
    messageCount += 1
    puts "Received message #{messageCount}: #{data}"
  else
    puts "empty"
  end
end

I put in the check for empty messages because I am seeing some odd
behaviour.
 Basically I can send a certain message to this client no problems
(message 1 to 4 below), but as soon as message 5 is received the program
hangs for 15 secs then goes into a mad loop of empty messages:


Received message 1: MESSAGET 18
1234 162 999 9999
Received message 2: MESSAGET 18
1234 162 999 9999
Received message 3: MESSAGET 18
1234 162 999 9999
Received message 4: MESSAGET 18
1234 162 999 9999
Received message 5: MESSAGET 35
0 162 9 0 "&" 82 -1000 2 9 25 "0"
empty
empty
empty
...


Something in that particular received message is making it go bonkers.
Any ideas?
Roger P. (Guest)
on 2009-01-23 02:57
> I tried something like this:
>
> loop {
>   data = socket.recv( 100 )
>   puts "Line received"
>   puts data
> }

recv should work--if you receive "" it means teh connection closed.
Cheers!
-=r
Brian C. (Guest)
on 2009-01-23 12:40
Chris B. wrote:
> while data = in_socket.recv( 100 )

Try using read(100) instead of recv(100).

read returns nil after the socket has been closed.

recv is a very low-level function, and I'd suggest using it only for UDP
datagrams.
Robert K. (Guest)
on 2009-01-23 18:12
(Received via mailing list)
2009/1/21 Chris B. <removed_email_address@domain.invalid>:
>  puts data
> }
>
> What I see when sending messages from the server is that the first
> message is received and printed, then the program hangs for 15 secs,
> then the loop starts but each time the data is empty.
>
> I am obviously doing something really stupid but I've spend hours now on
> this so if someone could hint at how to do this I would be most
> grateful.

Are both processes Ruby processes? In that case it's certainly a lot
more hassle free to use DRb.  If not, you should define a protocol
yourself.  Either use messages with a fixed length or transmit the
length as first item or use a special EOM marker (you could use a line
delimiter for this, which has the advantage that you can use gets or
each without arguments).

Kind regards

robert
This topic is locked and can not be replied to.