The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

IO::Socket::Timeout - IO::Socket with read/write timeout

VERSION

version 0.20

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.