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

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(); } } }

In reply to Using 'select' to handle multiple sockets by ikegami
in thread Signal handlers and scoped variables, or Nested subs? by kwaping

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.