tcp连接超时(unix / windows portable)

时间:2010-01-11 18:28:19

标签: tcp timeout connect

我正在使用perl(希望不会影响任何东西),但我需要知道如何设置连接操作的超时。问题是我不能永远等待连接操作发生。如果它在几秒钟内没有发生,我宁愿放弃并继续前进。

socket(my $sock, PF_INET, SOCK_STREAM, (getprotobyname('tcp'))[2]);
setsockopt($sock, SOL_SOCKET, SO_SNDTIMEO, 10); # send timeout

print "connecting...\n";
connect($sock, sockaddr_in(80,scalar gethostbyname('lossy.host.com')));
print "connected...\n";

问题是,如果与“lossy.host.com”的连接是“有损”或缓慢或者除了快速之外,我宁愿放弃而不是让用户等待。 (把它想象成一个程序的副作用,做一些其他事情......用户可能不希望这个脚本与某个服务器通信......)。

线程案例:你如何打断connect()?你会分开线程并忘掉它吗?

3 个答案:

答案 0 :(得分:2)

您可以使用fcntl将套接字设置为非阻塞,然后select使用超时等待它变为可读。如果在超时之前它不可读,则可以在此时关闭它。

我知道怎么用C语言,但不是perl,否则我会给你一个例子。 perlfunc手册页说所有这些函数都存在,粗略阅读似乎说它们会像你想要的那样工作。

编辑:抱歉,错过了perlfunc表示他们可能无法在非Unix系统上使用的部分,事实上,fcntl在win32上不可用。你可以使用一个IO :: Socket库,它可以在Windows上做正确的事情。

这是适用于我的示例代码(无论如何在linux上):

#!/usr/bin/perl

use IO::Socket::INET;
use IO::Select;

$sock = IO::Socket::INET->new('PeerAddr' => 'lossy.host.com',
                              'PeerPort' => 80,
                              'Blocking' => 0 );

$sel = IO::Select->new( $sock );

@writes = $sel->can_write(10);

if ( $sock->connected ) {
    print "socket is connected\n";
} else {
    print "socket not connected after however long\n";
    $sock->close;
}

答案 1 :(得分:1)

您可以生成一个单独的线程来执行此操作,然后定时等待结果。如果您没有在适当的时间内收到结果,请放弃等待,然后让线程继续。它最终会超时,或者你可能会杀死该线程。

要回答最初的问题,我认为没有办法改变connect()超时,至少不能通过套接字API。在Windows上,如果有一个可以改变的注册表项会影响它,我不会感到惊讶,但我不知道它会是什么。

答案 2 :(得分:0)

如果您最终执行线程情况,其中您分离连接线程而不将其删除,请注意以下事项:Windows仅允许您最多有10个待处理的传出TCP连接(第11个将阻塞,直到其中一个待处理的时间出)。

这对我来说是非常沮丧的原因。我认为MS这样做是为了防止僵尸网络传播或其他什么。我认为没有办法将其关闭。