socket_connect does not timeout

走远了吗. 提交于 2019-12-19 04:05:43

问题


I am using sockets to send data to a server that may not be responding. So I am trying to define a timeout by using this solution in SO.

Make PHP socket_connect timeout

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));

This works when the connection is made and the server takes too long to respond. But when it can't create a connection socket_connect($socket, $addr, $port); the timeout is about 20 seconds.

Why is this 20 second timeout happening and how can I force the connection creation to timeout after 1 second too?


回答1:


You can do this by switching to a non-blocking socket, looping until either a connection is gained or a timeout was reached, then back to blocking again.

// 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);

edit: see @letiagoalves answer for an neater solution if you are using sockets created with fsockopen() or stream_socket_client()




回答2:


I changed my socket communication mechanism to use stream_socket_client ($remote_socket, &$errno, &$errstr, $timeout) function instead. This function allows to define the connect timeout unlike socket_connect ($socket, $address, $port) which doesn't.

To force a timeout using socket_connect see @bigtallbill answer.




回答3:


The SO_RCVTIMEO/SO_SNDTIMEO options don't work for socket_connect on some platforms, but only for socket_recv/socket_send. I can see it works on Ubuntu, but not Mac OSX.




回答4:


I tried a lot of variants with sockets..

fsockopen the best for simple operations, ex. testing connections



来源:https://stackoverflow.com/questions/16689932/socket-connect-does-not-timeout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!