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); } } }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: poorly documented behaviour of readline() and IO::Select
by ikegami (Patriarch) on Jun 09, 2010 at 19:19 UTC |