Welcome to WebmasterWorld Guest from 54.205.115.177

Forum Moderators: coopster & jatar k & phranque

Message Too Old, No Replies

IO::Socket::INET and timeout

doesn't work

   
3:16 pm on Jul 17, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Tried using timeout option in the IO::Socket::INET module and it doesn't work. I looked in the source code of the INET.pm and the whole timeout option was commented out.

Is there a way to make it work?

4:37 pm on Jul 18, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> Is there a way to make it work?

Remove the comment marks in the package source? ;)

The commenting out seems strange - what version of IO::Socket are you using?

4:42 pm on Jul 18, 2003 (gmt 0)

WebmasterWorld Administrator brett_tabke is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



I spent over an hour yesterday trying to figure out an answer to this question. I tried removing the commenting too, but even under linux it didn't make a difference.

I thought at first the commenting was for the winders version only, but it doesn't appear to be.

4:52 pm on Jul 18, 2003 (gmt 0)

WebmasterWorld Senior Member littleman is a WebmasterWorld Top Contributor of All Time 10+ Year Member



On a Debian system I was using this routine without any hanging.

$remote = IO::Socket::INET->new(
Proto => "tcp",
Timeout => "5",
PeerAddr => $host,
PeerPort => "http($port)",
);

my $content;
if ($remote) {
$remote->autoflush(1);
print ">>flushed>>";
print $remote "GET $document HTTP/1.1" . $EOL;
print $remote "Host: $host" . $EOL;
print $remote
'User-Agent: Mozilla/5.0 Galeon/1.2.6 (X11; Linux i686; U;) Gecko/20020913 Debian/1.2.6-2'
. $EOL;
print $remote
'Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1'
. $EOL;
print $remote "Connection: close" . $EOL;
print $remote $EOL;
print $remote $EOL;
print " asked for $document..";

while (<$remote>) {
$content .= $_;

#print
}

close $remote;
print "closed connection";

6:32 pm on Jul 18, 2003 (gmt 0)

10+ Year Member



I've struggled with this a while ago and could not make it work. I don't remember exactly what the source of the problem was (I've found a document that explained it), but it was rather low-level and only present on certain OS'es.

I finally reverted to a workaround using alarm(), which worked fine for me.

BTW, timeout funtion in LWP does work, so a better answer may be hidden in the LWP source.

7:03 pm on Jul 18, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



sugarkane:
I am using v1.25. The newest one is v1.26, but Timeout is still commented out.

Brett_Tabke:
Yes, I've tried commenting out and playing around with it, in both Windows and Linux, and also have no luck! :(

littleman:
Yes, there is no hanging, if you pass Timeout option to the module, it just doesn't do anything. Did you ever try to timeout on purpose. Did it work? Try to connect to a host that does not exist. It will most likely hang. Unless the version of the module on Debian is somewhat different from RedHat or Windowz.

Storyteller:
Would you want to sticky me or post it here an example of alarm() code?

Thanks to everybody.

P.S. I also emailed this question to the developer, still waiting for reply.

1:23 pm on Jul 20, 2003 (gmt 0)

10+ Year Member



moltar, I replaced that code with an LWP call long ago. I'm almost certain I got the idea from O'Reilly's "Perl Cookbook" accompanying sources. May I suggest googling on 'perl alarm timeout socket'
2:20 am on Jul 22, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Storyteller: the thing is that this is not for HTTP requests. It's for WHOIS requests and LWP doesn't allow that. Internic server keeps timing out all the time and my script gets stuck and never ends.
6:09 pm on Jul 22, 2003 (gmt 0)

WebmasterWorld Senior Member littleman is a WebmasterWorld Top Contributor of All Time 10+ Year Member



I can't get this to hang at all no mater what address I feed it...tested on a Debian box.

use IO::Socket;
$host = "whatever.whatever";
my $EOL = "\015\012"; ## a CR LF pair for the server
$remote = IO::Socket::INET->new(
Proto => "tcp",
Timeout => "5",
PeerAddr => $host,
PeerPort => "http(80)",
);

my $content;
if ($remote) {
$remote->autoflush(1);
print ">>flushed>>";
print $remote "GET $document HTTP/1.1" . $EOL;
print $remote "Host: $host" . $EOL;
print $remote
'User-Agent: Mozilla/5.0'
. $EOL;
print $remote
'Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1'
. $EOL;
print $remote "Connection: close" . $EOL;
print $remote $EOL;
print $remote $EOL;
print " asked for $document..";

while (<$remote>) {
$content .= $_;

print
}
}
close $remote;
print "closed connection"

11:45 pm on Jul 23, 2003 (gmt 0)

10+ Year Member



As far as I know, two things are to be kept in mind when using the timeout function provided by IO::Socket (though I have no idea why it's commented out):

1. The module only checks for a timeout during the socket connect handshake, not for reads or writes! It does this by setting the socket to non-blocking (via IO::Select) during connect.
2. If you set Timeout, another module - IO::Select - is called in which adds to the overhead except if you already utilize it in your application.

If you need a fine-tuned solution offering the most flexibility (timing, autoflush, non-blocking, etc.) or a portable timeout solution working both on UNIX and WINDOWS, you'd have to use your own "select/vec" calls on each socket operation - and probably also handle the socket methods yourself (via "use Socket").

Else, I often use the system alarm call wrapped in an eval of the entire socket routine. I.e., using IO::Socket:

eval {
local $SIG{ALRM} = sub { die 'Timed Out'; };
alarm 3;
my $sock = IO::Socket::INET->new(
PeerAddr => inet_ntoa( gethostbyname($host) ),
PeerPort => 'whois',
Proto => 'tcp',
## Timeout => ,
);
$sock->autoflush;
print $sock "$qry\015\012";
undef $/; $data = <$sock>; $/ = "\n";
alarm 0;
};
alarm 0; # race condition protection
return "Error: Timeout." if ( $@ && $@ =~ /Timed Out/ );
return "Error: Eval corrupted: $@" if $@;

Just remember to not mix sleep with alarm calls when running on Linux.