EMA has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, This is my first program using sockets, so I might be doing something foolish - if so excuse me. I'm trying to write a simple client which connects to a server, receives data, processes it, and prints it to the screen. The problem I am having is that the program hangs for 20-30 seconds, prints out a spurt of data, and does this several times before the connection times out on the server. Here's the code:
{ $sock = new IO::Socket::INET ( PeerAddr => $host, PeerPort => $port, Proto => 'tcp', Reuse => 1 ); $sock->autoflush(1); print $sock "log in information"; my $read_set = new IO::Select($sock); my $incoming_server_data = ""; while (1) { my @ready = $read_set->can_read(.5); foreach my $rh (@ready) { my $line = <$rh>; $incoming_server_data .= $line; parse(\$incoming_server_data); } } }
The printing is done inside the parse function. I thought that might be the problem, but replacing the call to parse() with a simple print "$line\n"; did not change the problem.
Update
Answered! Changing my $line = <$rh>; to sysread $rh, my $line, 1024;, per etcshadow's suggestion, did the trick. Thanks!

Replies are listed 'Best First'.
Re: IO::Socket hanging
by etcshadow (Priest) on Nov 22, 2004 at 06:57 UTC
    The basic issue is that <$rh> does a buffered read from the socket, meaning that it won't return from the read call until $/ (defaults to "\n") is encountered on the channel. IO::Select::can_read just means that there is data on the channel, it does not necessarily mean that there is a full record (defined as: a chunk terminated with an occurence of $/) waiting on the channel.

    The proper solution is either to change (locally) the value of $/ to whatever makes sense for the records you are sending accross the channel... if you are willing to rely on the fact that only complete records get sent (otherwise you can gum up the process with blocking incomplete buffered reads), OR to change it from a buffering read to a non-buffering read (the better but more involved solution). For that, take a look at perldoc -f sysread for more details.

    ------------ :Wq Not an editor command: Wq
Re: IO::Socket hanging
by Luca Benini (Scribe) on Nov 22, 2004 at 06:53 UTC
    Try to protect the block
    my $line = <$rh> $incoming_server_data .= $line; parse(\$incoming_server_data);
    with a  if($rh == $sock) block