Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Using 'select' to handle multiple sockets

by ikegami (Pope)
on May 13, 2006 at 06:58 UTC ( #549191=note: print w/ replies, xml ) Need Help??


in reply to Re^2: Signal handlers and scoped variables, or Nested subs?
in thread Signal handlers and scoped variables, or Nested subs?

Partially tested. Specifically, I've tested the following:

  • If it's the first time you can write to a socket, then it has just been connected.
  • A socket will be flagged as readable when it gets disconnected. eof will return true on this socket.

You should find the following code very flexible. Think of Client as a state machine.

use IO::Select (); use IO::Socket::INET (); use Time::HiRes qw( time ); # Optional. { package Client; use constant ST_CONNECTING => 0; use constant ST_SOMETHING1 => 1; use constant ST_SOMETHING2 => 2; use constant ST_SOMETHING3 => 3; # ... sub new { my ($class) = @_; my $self = bless({ sock => $sock, timeout => time() + 30, wannna_d => 0, # True if we want to disconnect the socket. wannna_w => 1, # True if we want to write to the socket. state => ST_CONNECTING, # ... }); } sub connected { my ($self) = @_; $self->{state } = ST_SOMETHING1; $self->{wanna_w} = 0; # ... } sub disconnected { my ($self) = @_; # ... } sub timed_out { my ($self) = @_; # ... } sub data_available { my ($self) = @_; $self->reset_timeout(); # ... } sub ready_to_write { my ($self) = @_; $self->reset_timeout(); my $state = $self->{state}; if ($state == ST_CONNECTING) { $self->connected(); return; } # ... } sub reset_timeout { my ($self) = @_; $self->{timeout} = $time + 30; } } { my %clients; { my $sock = IO::Socket::INET->new( Proto => 'tcp', PeerAddr => '...', Blocking => 0, # How well does this work in Windows? ); $clients{$sock} = Client->new($sock); } for (;;) { my $time = time; my $min_timeout = 3600; # Just so it isn't undef. my $r_sel = IO::Select->new(); my $w_sel = IO::Select->new(); foreach my $client (values %clients) { my $sock = $client->{sock}; my $wanna_d = $client->{wanna_d}; my $wanna_w = $client->{wanna_w}; my $timeout = $client->{timeout} - $time; if ($wanna_d) { delete($clients{$sock}); next; } if ($timeout <= 0) { delete($clients{$sock}); $client->timed_out(); next; } $min_timeout = $timeout if $min_timeout > $timeout; $r_sel->add($sock); $w_sel->add($sock) if $wanna_w; } # In case a "$client->timed_out();" takes a long time. $timeout -= time() - $time; $timeout = 0.001 if $timeout < 0; last if not %clients; my ($r, $w) = IO::Select->select($r_sel, $w_sel, undef, $timeout); foreach my $sock (@$r) { my $client = $clients{$sock}; next if not $client; # Just in case. if (eof($sock)) { delete($clients{$sock}); $client->disconnected(); } else { $client->data_available(); } } foreach my $sock (@$w) { my $client = $clients{$sock}; next if not $client; $client->ready_to_write(); } } }


Comment on Using 'select' to handle multiple sockets
Select or Download Code

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2014-09-22 03:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (177 votes), past polls