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

I have a server based on the following IO::Select example code with non-blocking clients. It does not recognise when the connection is closed by the other end... the handle still is still opened() and not in error() and the select->has_exception list is empty. On the other hand the select->can_read in this example goes into a tight loop. How do I fix this whilst still using non blocking IO (and is using getlines ok with NIO?)
$server = new IO::Socket::INET(Listen => 1, LocalPort => 8080) || +die "$!"; $sel = new IO::Select( $lsn ); while(@ready = $sel->can_read) { foreach $fh (@ready) { if($fh == $server) { # Create a new socket $new = $lsn->accept; $new->blocking(0); $sel->add($new); } else { # Process socket print "ERROR ",$fh->error," OPENED ",$fh->opened,"\n"; print $fh -> getlines; }

Replies are listed 'Best First'.
Re: IO::Select->can_read isn't recognising closed INET connections
by ptkdb (Monk) on Nov 10, 2003 at 13:26 UTC
    When a client's INET socket is closed, the socket on the server's end will show up as 'ready', but the next read from it will read 0 bytes, or in perl's case as 'undef' if you read it with <$socket>. In the case of 'non-blocking' io, if you get a positive can_read() and read length of 0, then the socket was closed on the other end.
    @reads = $select->can_read() ; for( @reads ) { $data = <$_> ; if( $data == undef && $! != EWOULDBLOCK ) { # socket closed from the other end } }
    Reference: Unix Network Programming 2nd Ed Vol 1 page 166-167, by W. Richard Stevens
Re: IO::Select->can_read isn't recognising closed INET connections
by etcshadow (Priest) on Nov 10, 2003 at 20:20 UTC
    ptdkb++. Also, you should be checking the error-condition (out-of-band data) on your sockets. So instead of just using $sel->can_read, try checking:
    my (undef, $can_read, $has_error) = $sel->select(undef, undef, undef); foreach my $fh (@$can_read) { ... } foreach my $fh (@$has_error) { ... }

    ------------
    :Wq
    Not an editor command: Wq