Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re^3: poorly documented behaviour of readline() and IO::Select

by ikegami (Pope)
on Apr 28, 2010 at 14:44 UTC ( #837324=note: print w/ replies, xml ) Need Help??


in reply to Re^2: poorly documented behaviour of readline() and IO::Select
in thread poorly documented behaviour of readline() and IO::Select

sysread won't always give you the amount of bytes you request when reading from something that isn't a plain file.

See Re: A suicidal parent OR death of a forking server for a newline terminated solution, and here's a length-prefix adaptation:

#!/usr/bin/perl use strict; use warnings; use IO::Socket::INET qw( ); use IO::Select qw( ); sub process_msg { my ($client, $msg) = @_; chomp $msg; print "$client->{host} said '$msg'\n"; } sub process_msgs { my ($client) = @_; our $buf; local *buf = \($client->{buf}); our $want; local *want = \($client->{want}); for (;;) { if ($want) { return if length($buf) < $want; my $msg = substr($buf, 0, $want, ''); $want = 0; process_msg($client, $msg); } else { return if length($buf) < 8; $want = 0+substr($buf, 0, 8, ''); } } } my $server = IO::Socket::INET->new( ... ) or die("Couldn't create server socket: $!\n"); my $select = IO::Select->new($server); my %clients; while (my @ready = $select->can_read) { for my $fh (@ready) { if ($fh == $server) { my $client_sock = $server->accept; my $host = $client_sock->peerhost; print "[Accepted connection from $host]\n"; $select->add($client_sock); $clients{fileno($client_sock)} = { host => $host, buf => '', want => 0, }; } else { my $client = $clients{fileno($fh)}; our $buf; local *buf = \($client->{buf}); our $want; local *want = \($client->{want}); my $rv = sysread($fh, $buf, 64*1024, length($buf)); if (!$rv) { my $host = $client->{host}fh->peerhost; if (defined($rv)) { print "[Error reading from host $host]\n"; } else { print "[Connection from $host terminated]\n"; } process_msgs($client); print "Incomplete message received from $host]\n" if $want || length($buf); delete $clients{fileno($fh)}; $sel->remove($fh); next; } process_msgs($client); } } }


Comment on Re^3: poorly documented behaviour of readline() and IO::Select
Download Code
Replies are listed 'Best First'.
Re^4: poorly documented behaviour of readline() and IO::Select
by ikegami (Pope) on Jun 09, 2010 at 19:19 UTC

    Instead of implementing a limited cooperative multitasking system using select, it's simpler to use threads or Coro.

    The following is the Coro equivalent of the code in the parent post.

    #!/usr/bin/perl use strict; use warnings; use Coro qw( async ); use IO::Socket::INET qw( ); sub _read { my $rv = read($_[0], $_[1], $_[2], $_[3]||0); die("Read error\n") if !defined($rv); return if !$rv; die("Premature end of file\n") if $rv != $_[1]; } sub client { my ($sock) = @_; my $host = $client->peerhost; print "[Accepted connection from $host]\n"; if (defined(eval { for (;;) { _read($sock, 8, my $buf = '') or last; my $length = 0+$buf or next; _read($sock, $length, my $msg = '') or die("Premature end of file\n"); print "$host said '$msg'\n"; } })) { print "[Connection from $host terminated]\n"; } else { print "[Connection from $host terminated: $@]\n"; } } my $server = IO::Socket::INET->new( ... ) or die("Couldn't create server socket: $!\n"); async(\&client, $server->accept) while 1;

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (8)
As of 2015-07-29 02:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (260 votes), past polls