Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
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 meditating upon the Monastery: (3)
As of 2014-09-24 05:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

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











    Results (246 votes), past polls