I'm going through docs and howtos I'm finding on proper usage of IO::Select in terms of network socket communications. I think I've got my head wrapped around most of it.
However, I'm still kind of fuzzy on proper error handling. Say I've something similar to the following code running inside an object. Yes, I do realize it's messy, I should integrate IO::Select into the object and not the socket fh itself, I shouldn't recreate the IO::Select each time through the loop, I'm iterating over what can only ever be a single returned filehandle, etc. However, this keeps the example simple.
This is just a client connecting to a server, but one which I want to be able to properly handle network level errors such as packet loss.
Edit: $self->sock()
returns just an opened IO::Socket::INET socket.
sub read {
my $self = shift;
my($length) = @_; ### Number of bytes to read from the socket
my $ret;
while (length($ret) < $length) {
my $str;
use IO::Select;
my $sel = IO::Select->new($self->sock());
if (my @ready = $sel->can_read(5)) { ### 5 sec timeout
for my $fh (@ready) {
my $recv_ret = $fh->recv($str, $length - length($ret));
if (!defined $recv_ret) {
MyApp::Exception->throw(
message => "connection closed by remote host: $!",
);
}
}
}
else {
### Nothing ready... we timed out!
MyApp::Exception->throw(
message => "no response from remote host",
);
}
$ret .= $str;
}
return $ret;
}
1) I would check just in case. When it comes to select(2), defensive programming is your friend.
2) Suppose you need 2048 bytes and remote host sends a byte every 5 seconds. You've just hung for 10K seconds = 3 hours. Is that what you want?
I would use alarm 5
and $SIG{ALRM} = sub {$stop = 1;}
instead.
3 and 4) From my experience, just read() while select()
does the job but I can't give a sure answer here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With