我正在使用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()?你会分开线程并忘掉它吗?
答案 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这样做是为了防止僵尸网络传播或其他什么。我认为没有办法将其关闭。