PHP设置套接字超时不起作用?

时间:2017-05-08 18:07:44

标签: php sockets

我试图在我的php函数下面设置一个超时,以避免页面加载需要一段时间,但我需要通过php在页面加载时将tcp消息发送到ip和端口,如何设置超时如果ip和端口无法访问?

我尝试过使用下面的socket_set_option方法,但不幸的是它需要30秒,有时甚至更长。

我在laravel 5.2项目中使用它

public static function send($command, $data = '')
{
    $MUSdata = $command . chr(1) . $data;
    $socket = \socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));

    $connect_timeval = array(
        "sec"=>0,
        "usec" => 100
    );

    \socket_set_option(
        $socket,
        SOL_SOCKET,
        SO_SNDTIMEO,
        $connect_timeval
    );

    \socket_connect($socket, Config::get('frontend.client_host_ip'), Config::get('frontend.mus_host_port'));
    \socket_send($socket, $MUSdata, strlen($MUSdata), MSG_DONTROUTE);     
    \socket_close($socket);
}

1 个答案:

答案 0 :(得分:1)

我根据Brian comment写了一个connect_with_timeout函数:

  

不幸的是,SO_SNDTIMEO不会影响连接超时;连接套接字后才进行写操作。您需要将套接字置于非阻塞模式,为连接编写自己的超时循环(将返回EAGAIN直到套接字连接),然后将套接字重新置于阻塞模式。

如果套接字及时连接,则该函数返回true,否则返回false。 $timeout是以秒为单位的超时,$con_per_sec是每秒的连接尝试次数。

function connect_with_timeout($soc, $host, $port, $timeout = 10) {
    $con_per_sec = 100;
    socket_set_nonblock($soc);
    for($i=0; $i<($timeout * $con_per_sec); $i++) { 
        @socket_connect($soc, $host, $port);
        if(socket_last_error($soc) == SOCKET_EISCONN) { 
            break;
        }
        usleep(1000000 / $con_per_sec);
    }
    socket_set_block($soc);
    return socket_last_error($soc) == SOCKET_EISCONN;
}

在Windows和Linux上测试,PHP 5.x