http://www.perlmonks.org?node_id=1106025


in reply to Re: use sysread to read non-blocking filehandle
in thread use sysread to read non-blocking filehandle

If there is nothing to read,it means the sysread has finished all the reading, I should see something in the results?

Replies are listed 'Best First'.
Re^3: use sysread to read non-blocking filehandle
by roboticus (Chancellor) on Nov 04, 2014 at 13:18 UTC

    x12345:

    Not exactly--it can also mean "I haven't received a response yet". So you're probably terminating the loop before the other side ever had a chance to reply. (Considering the timing, you may be exiting before the other computer even received the request.)

    Update: It can also mean "The network is really busy, so the next packet hasn't arrived yet." That could be a problem if you've received only part of your response.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      Could you show me how to change my code to get the results?

        x12345:

        This is a bit oversimplified, as there's insufficient error checking and such. But I'd suggest doing something like "terminate the loop if I haven't received anything for X seconds" (where you'd have to choose X to balance between performance, and the possibility of a false failure). You could start with something like this:

        my $timeout = time+$X; # timeout if we don't see anything in $X secon +ds my $ttl_bytes_rcvd=0; # haven't received anything yet while (time < $timeout) { ... read the data ... if ($bytes_read>0) { $timeout = time+$X; # Reset timeout if we actually saw some data $ttl_bytes_rcvd += $bytes_read; } # don't just hammer the CPU, give other processes a chance to do so +mething, # as well as allowing a bit of time for more data to arrive sleep 0.5; } if ($ttl_bytes_rcvd) { # process successful response ... } else { die "Error! No data received!\n"; }

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

        You could check whether you closed your session and don't expect any more data. Maybe eof could help there too.

        Using these two criteria, you should be able to determine whether there was just not anything read, or whether the other end has closed the connection.

Re^3: use sysread to read non-blocking filehandle
by ikegami (Patriarch) on Nov 04, 2014 at 17:00 UTC

    If there is nothing to read,it means the sysread has finished all the reading?

    Or an error. You got error EAGAIN. That error signifies that sysread should block, but the file handle is non-blocking.

    EAGAIN or EWOULDBLOCK: The file descriptor fd refers to a socket and has been marked nonblocking (O_NON-BLOCK), and the write would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.

    What you want:

    my $buf; while (1) { my $rv = sysread($out, $buf, 64*1024, length($buf)); if (!defined($rv) && !$!{EAGAIN} && !$!{EWOULDBLOCK}) { die $!; } if (defined($rv) && !$rv) { last; } ... whatever it is you wanted to do instead of blocking ... } print $buf;
Re^3: use sysread to read non-blocking filehandle
by x12345 (Novice) on Nov 05, 2014 at 13:04 UTC
    I found the problem in my loop, after use perl -d debugger, it is the $bytes_read should be "my $bytes_read", in the code, it is defined twice, it is a little bit confused, should have better clear way to do that, but in the code I have, it is like that, and when I rewrite the code, I remove my in frond $bytes_code in the while loop, which was wrong. So it should be
    my $bytes_read = sysread($fh,$bug,$blocksize)