Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

IO::Handle read error description?

by Marcello (Hermit)
on Nov 03, 2006 at 10:32 UTC ( #582048=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

I am using a server IO::Socket for incoming TCP connections. The program uses the IO::Handle->getline() function to read the command up to the command delimiter. This function is called only after verifying that data is available with IO::Select.

However, one client connection is occassionally giving problems during the reading of commands. The getline() functions returns a partial command and IO::Handle->error() is 1. The TCP connection is still alive, and after a few seconds the remaining data comes available for reading.

Is there any way I can get an error description to what happended here? I verified that the client program sending is not sending out these partial commands, it is writing whole commands to the server handle. Could it be a TCP packet size issue which is splitting commands into partial packets, where the second packet is received with a short delay? Anyone else experienced these partial commands?

In order to solve this problem, I would like to understand what is causing these partial commands.

Any help is appreciated.

Kind regards,
Marcel

Replies are listed 'Best First'.
Re: IO::Handle read error description?
by ikegami (Pope) on Nov 03, 2006 at 16:15 UTC

    You can't rely on the commands making it through in one piece.

    Furthermore, there are recommendations to avoid using buffered IO (<SOCK>, read, eof, getline, getlines) in the docs. sysread is not buffered.

    • For each socket with data available (as returned by select),
      • Read (using sysread) from the socket.
      • If sysread returned undef,
        • Remove socket from the select object.
        • Handle error socket.
      • If sysread returned zero,
        • Remove socket from the select object.
        • Handle closed socket.
      • Append to the socket's buffer the data that was read from the socket.
      • While the buffer has a full line/command in it,
        • Extract the line/command from the buffer (leaving the rest in the buffer).
        • Process the extracted line/command.
    my ($r_ready, $w_ready) = IO::Select::select($r_sel, $w_sel); foreach my $sock (@$r_ready) { # Create alias to the appropriate buffer. our $buf; local *buf = \$in_bufs{$sock}; my $rv = sysread($sock, $buf, 4096, length($buf)); # Read error. if (not defined $rv) { $r_sel->remove($sock); # ... Handle error socket ... next; } # Socket EOF if (not $rv) { $r_sel->remove($sock); # ... Handle closed socket ... next; } for (;;) { # Search for a complete command. my $pos = index($buf, "\x0A"); last if $pos < 0; my $cmd = substr($buf, 0, $pos+1, ''); # ... process $cmd ... } } foreach my $sock (@$w_ready) { # ... }

    Update: Added code.
    Update: Bug fix to handle the case where multiple commands in the buffer.

      hm. for this socket should be in non-blocking mode, right ?

        No. The whole point of using select is to let us know when reading from the socket won't block and when writing to the socket won't block.

        Unfortunately, it doesn't tell us how much we can write to it without blocking. We only know that we can write one byte without blocking. Maybe non-blocking sockets would help in the writing half. Ideally, there would be a system call that tells us how much we can write without writing. I don't know if there is one.

Re: IO::Handle read error description?
by Hofmator (Curate) on Nov 03, 2006 at 10:45 UTC
    Have you tried printing the $! variable after the getline() call?

    -- Hofmator

    Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      I was thinking of the same thing. I ran into this once, and and I believe that it was this very thing, but it was so long ago that I can't recall. I do recommend trying it, however.

      --
      tbone1, YAPS (Yet Another Perl Schlub)
      And remember, if he succeeds, so what.
      - Chick McGee

      Good one,

      I have modified the code to log also the $! variable. Now we wait for the error to occur again. The question remains why these partial commands are received. Sometimes it takes up to 5 seconds to receive the second part, which might indicate that TCP packets are being delayed somewhere.

      Regards,
      Marcel

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://582048]
Approved by tbone1
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2020-06-02 00:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you really want to know if there is extraterrestrial life?



    Results (12 votes). Check out past polls.

    Notices?