5

我正在使用 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()?你会只是分离线程并忘记它吗?

4

3 回答 3

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;
}
于 2010-02-17T20:44:44.103 回答
1

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

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

于 2010-01-11T18:31:11.183 回答
0

如果您最终执行了线程案例,其中您分离连接线程而不杀死它,请注意以下事项:Windows 只允许您拥有最多 10 个待处理的传出 TCP 连接(第 11 个将阻塞,直到其中一个待处理的连接超时)。

这是我非常沮丧的原因。我认为 MS 将其放入以防止僵尸网络传播或其他东西。我也不认为有什么办法可以关掉它。

于 2010-02-17T21:40:23.760 回答