NAME
IO::Socket::Timeout - IO::Socket with read/write timeout
VERSION
version 0.18
SYNOPSIS
use IO::Socket::With::Timeout;
# creates a IO::Socket::INET::With::Timeout object
my $socket = IO::Socket::INET->new::with::timeout( Timeout => 2,
ReadTimeout => 0.5,
# other standard arguments );
my $socket = IO::Socket::UNIX->new::with::timeout( Timeout => 2,
ReadTimeout => 0.5,
WriteTimeout => 0.5,
# other standard arguments );
my $socket = IO::Socket::INET->new::with::timeout( Timeout => 2,
ReadWriteTimeout => 0.5,
# other standard arguments );
# When using the socket:
use Errno qw(ETIMEDOUT EWOULDBLOCK);
print $socket $request;
my $response = <$socket>;
if (! $response && ( 0+$! == ETIMEDOUT || 0+$! == EWOULDBLOCK )) {
die "timeout reading on the socket";
}
DESCRIPTION
IO::Socket
provides a way to set a timeout on the socket, but the timeout will be used only for connection, not for reading / writing operations.
This module provides a way to set a timeout on read / write operations on an IO::Socket
instance, or any IO::Socket::*
modules, like IO::Socket::INET
.
CONSTRUCTORS
new::with::timeout
To be able to work with any class that is or inherits from IO::Socket, the interface of this module is a bit unusual.
IO::Socket::INET-
new::with::timeout(...)> will return an instance of IO::Socket::INET
, as if it had been called with IO::Socket::INET-
new(...)>. However, it'll apply some mechanism on the resulting socket object so that it times out on read, write, or both.
The way the socket will timeout ( on connection, read, write, how long), can be specified with these parameters:
- Timeout
-
This is the default parameter that already exists in IO::Socket. If set to a value, the socket will timeout at connection time.
- ReadTimeout
-
If set to a value, the socket will timeout on reads. Value is in seconds, floats accepted.
- WriteTimeout
-
If set to a value, the socket will timeout on writes. Value is in seconds, floats accepted.
- ReadWriteTimeout
-
If set to a value, the socket will timeout on reads and writes. Value is in seconds, floats accepted. If set, this option superseeds ReadTimeout and WriteTimeout.
socketpair::with::timeout
There is an other way to create sockets from scratch, via socketpair
. As for the new
constructor, this module provides its counterpart with timeout feature.
IO::Socket::INET-
socketpair::with::timeout(...)> will return two instances of IO::Socket::INET
, as if it had been called with IO::Socket::INET-
socketpair(...)>. However, it'll apply some mechanism on the resulting socket object so that it times out on read, write, or both.
METHODS
read_timeout
my $current_timeout = $socket->read_timeout();
$socket->read_timeout($new_timeout);
Get or set the read timeout value for a socket created with this module.
write_timeout
my $current_timeout = $socket->write_timeout();
$socket->write_timeout($new_timeout);
Get or set the write timeout value for a socket created with this module.
disable_timeout
$socket->disable_timeout;
Disable the read and write timeouts for a socket created with this module.
enable_timeout
$socket->enable_timeout;
Re-enable the read and write timeouts for a socket created with this module.
timeout_enabled
my $is_timeout_enabled = $socket->timeout_enabled();
$socket->timeout_enabled(0);
Get or Set the fact that a socket has timeouts enabled.
CHANGE SETTINGS AFTER CREATION
You can change the timeout settings of a socket after it has been instanciated.
use IO::Socket::With::Timeout;
# create a socket with read timeout
my $socket = IO::Socket::INET->new::with::timeout( Timeout => 2,
ReadTimeout => 0.5,
# other standard arguments );
# change read_timeout to 5 and write timeout to 1.5 sec
$socket->read_timeout(5)
$socket->write_timeout(1.5)
# actually disable the timeout for now
$socket->disable_timeout()
# when re-enabling it, timeouts value are restored
$socket->enable_timeout()
WHEN TIMEOUT IS HIT
When a timeout (read, write) is hit on the socket, the function trying to be performed will return undef
or empty string, and $!
will be set to ETIMEOUT
or EWOULDBLOCK
. You should test for both.
You can import ETIMEOUT
and EWOULDBLOCK
by using POSIX
:
use Errno qw(ETIMEDOUT EWOULDBLOCK);
IF YOU NEED TO RETRY
If you want to implement a try / wait / retry mechanism, I recommend using a third-party module, like Action::Retry
. Something like this:
my $socket;
my $answer;
my $action = Action::Retry->new(
attempt_code => sub {
# (re-)create the socket if needed
$socket && ! $socket->error
or $socket = IO::Socket->new::with::timeout(ReadTimeout => 0.5);
# send the request, read the answer
$socket->print($_[0]);
defined($answer = $socket->getline) or die $!;
$answer;
},
on_failure_code => sub { die 'aborting, to many retries' },
);
my $reply = $action->run('GET mykey');
SEE ALSO
Action::Retry, IO::Select, PerlIO::via::Timeout, Time::Out
THANKS
Thanks to Vincent Pitt, Christian Hansen and Toby Inkster for various help and useful remarks.
AUTHOR
Damien "dams" Krotkine
COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by Damien "dams" Krotkine.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.