Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
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
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 making s'mores by the fire in the courtyard of the Monastery: (8)
As of 2014-11-22 21:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (125 votes), past polls