代码之家  ›  专栏  ›  技术社区  ›  dlamotte

tcp连接超时(unix/windows可移植)

  •  4
  • dlamotte  · 技术社区  · 15 年前

    我正在使用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”或“slow”或“fast”以外的任何东西,我宁愿放弃,也不愿让用户等待。(把它看作是一个程序做其他事情的副作用。。。用户可能不希望此脚本在某处与服务器通信。

    线程情况:如何中断connect()?你能把线拆开然后忘掉它吗?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Eric Warmenhoven    15 年前

    你可以用 fcntl 将套接字设置为非阻塞,然后 select 等待它变为可读的超时。如果在超时之前无法读取,则可以在此时将其关闭。

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

    文件锁 在win32上不可用。不过,有一个IO::Socket库,您可以使用它在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;
    }
        2
  •  1
  •   Graeme Perrow    15 年前

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

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

        3
  •  0
  •   Seth    15 年前

    这是我非常沮丧的原因。我想微软把这个放进去是为了防止僵尸网络扩散之类的。我想也没有办法关掉它。