socket_connect does not timeout


socket_connect does not timeout

我正在使用套接字向可能没有响应的服务器发送数据。因此,我试图通过在So中使用此解决方案来定义超时。

设置socket_connect超时

socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 1, 'usec' => 0));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 1, 'usec' => 0));

当建立连接并且服务器需要很长时间才能响应时,此方法有效。但是当它不能创建连接socket_connect($socket, $addr, $port);时,超时时间约为20秒。

为什么这20秒超时发生,我怎么能强制连接创建超时1秒后?

您可以切换到非阻塞套接字,循环直到获得连接或达到超时,然后再次返回阻塞。

// an unreachable address
$host = '10.0.0.1';
$port = 50000;
$timeout = 2;
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// switch to non-blocking
socket_set_nonblock($sock);
// store the current time
$time = time();
// loop until a connection is gained or timeout reached
while (!@socket_connect($sock, $host, $port)) {
    $err = socket_last_error($sock);
    // success!
    if($err === 56) {
        print('connected ok');
        break;
    }
    // if timeout reaches then call exit();
    if ((time() - $time) >= $timeout) {
        socket_close($sock);
        print('timeout reached!');
        exit();
    }
    // sleep for a bit
    usleep(250000);
}
// re-block the socket if needed
socket_set_block($sock);

编辑:如果您正在使用fsockopen()或stream_socket_client()创建的套接字

,请参阅@letiagoalves答案以获得更简洁的解决方案

我将套接字通信机制改为使用stream_socket_client ($remote_socket, &$errno, &$errstr, $timeout)函数。此函数允许定义连接超时,而socket_connect ($socket, $address, $port)不允许。

使用socket_connect强制超时,请参见@bigtallbill answer

我尝试了很多套接字的变体。

fsockopen最适合简单操作,例如测试连接

SO_RCVTIMEO/SO_SNDTIMEO选项在某些平台上不适用于socket_connect,而只适用于socket_recv/socket_send。我可以看到它在Ubuntu上运行,但在Mac OSX上不行