in reply to Non-blocking connect() and gethostbyname()?

For all this, I'm assuming that you're using a big select() to wait for all I/O and that you're not doing threads. (Threads would be one solution to all this, if they're supported on your perl/OS).

About gethostname():
I don't see any nonblocking DNS library on CPAN, so I think what you would have to do is create a pipe (or socket pair), fork, do the lookup in the child process and return the result via the pipe (you add the pipe to your select in the parent).

About connect():
Several possibilities:

  1. You don't have to use IO::Socket. You can use the plain socket functions, as documented in perlfunc. You can use the sockets returned by the socket() call in IO::Select->add or you can use plain select(), managing the bit vectors yourself (yuck).
  2. If you want an IO::Socket::INET object, you can create the socket with IO::Socket::INET new without a PeerAddr, then do the connect yourself. E.g.
    my $sock = IO::Socket::INET->new(Proto => 'tcp', Blocking => 0) or die "Socket error: $!\n"; my $iaddr = inet_aton($remote) || die "no host: $remote"; my $paddr = sockaddr_in($port, $iaddr); my $ret = connect($sock, $paddr); if (!$ret && ! $!{EINPROGRESS}) { die "Connect error: $!\n"; } # then select(), etc.
  3. Or, you could subclass IO::Socket::INET and override the connect method
    use strict; { package NBCSocket; use IO::Socket::INET; use Errno; use Carp; our @ISA = 'IO::Socket::INET'; sub connect { @_ == 2 or croak 'usage: $sock->connect(NAME)'; my $sock = shift; my $addr = shift; my $timeout = ${*$sock}{'io_socket_timeout'}; my $err; my $blocking; $blocking = $sock->blocking(0); if (!connect($sock, $addr)) { if (!$!{EINPROGRESS}) { $err = $!; $@ = "connect: $!"; } } $! = $err if $err; $err ? undef : $sock; } } use IO::Select; use Socket; $| = 1; my $address = shift || die "usage: $0 host:port\n"; $! = 0; my $err; print "Start: ", scalar(localtime), "\n"; my $sock = NBCSocket->new(PeerAddr => $address) or die "Socket error: $!\n"; print "after NBCSocket->new \$! = $!\n"; # of course, you'll probably want to do a select with other sockets $! = 0; my $select = IO::Select->new($sock); if ($select->can_write(5)) { my $peername = $sock->peername; if ($peername) { print "Connected: ", scalar(localtime), ", peername=$peername\n" +; } else { print "Not peername err = $!: ", scalar(localtime), "\n"; } } else { $err = $!; $sock_err = $sock->sockopt(SO_ERROR); print "Did not connect: ", scalar(localtime), "\n"; print "\$!=$err sock_err = $sock_err\n"; }

Replies are listed 'Best First'.
Re^2: Non-blocking connect() and gethostbyname()?
by mpeg4codec (Pilgrim) on Jan 06, 2008 at 02:17 UTC

    I've never used it, but wouldn't Net::ADNS do the trick for asynchronous DNS lookups?