tcp连接超时(unix/windows便携式)

tcp连接超时(unix/windows便携式),tcp,timeout,connect,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($soc

我正在使用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”的连接是“lossy”或慢速连接,或是任何不快速的连接,我宁愿放弃,也不愿让用户等待。(将其视为执行其他操作的程序的副作用…用户可能不希望此脚本在某处与服务器通信…)


线程情况:如何中断connect()?您是否可以分离该线程并将其忘记?

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


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

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

我知道如何在C语言中实现这一点,但不是perl,否则我会给你一个例子。perlfunc手册页上说,所有这些函数都存在,粗略的阅读似乎表明它们将按照您的意愿工作

编辑:很抱歉,错过了perlfunc说它们可能在非Unix系统上不可用的部分,实际上,
fcntl
在win32上不可用。不过,您可以使用一个IO::Socket库在Windows上执行正确的操作

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


如果最终执行的是线程情况,即分离连接线程而不终止它,请注意以下几点:Windows最多只允许10个挂起的传出TCP连接(第11个将被阻止,直到其中一个挂起的TCP连接超时)


这是我感到非常沮丧的原因。我认为微软把这个放进去是为了防止僵尸网络的传播。我也不认为有任何方法可以关闭它。

你能更具体一点吗?如何使用IO::Socket库实现这一点?将套接字设置为非阻塞?没错,在构造套接字时,将“阻塞”设置为0(即非阻塞)。它应该使用非阻塞连接。我尝试了这个,因为某些原因,我无法让它在我的windows设备上正常工作。。。你真的在windows上试过吗?我只在Linux上测试过。不幸的是,我没有一个windows的盒子来测试,否则我会。不过,通过查看文档,它看起来应该可以工作。你知道它在哪里失败了吗?听起来像是“windows要做的事情”。谢谢你!我会把它和所有其他窗口的零碎东西一起留在脑后;)
#!/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;
}