2017-05-08 73 views
1

我想设置一个超时在我的PHP函数下面,以避免页面加载需要一段时间,但我需要发送一个TCP消息通过PHP的页面加载一个IP和端口,如何设置一个超时事件该IP和端口无法访问?PHP设置套接字超时不起作用?

我已经尝试使用下面的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

不幸的是,'SO_SNDTIMEO'不影响连接超时;只有在套接字连接后才执行写入操作。您需要将套接字置于非阻塞模式,为连接编写自己的超时循环(这将返回EAGAIN,直到套接字连接),然后将套接字重新置于阻塞模式。我会发布这个答案,但我不确定如果PHP支持的话。 –

回答

0

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

基于@Lotharyx的评论,我写了一个小的connect_with_timeout函数。
如果套接字及时连接,则函数返回true,否则返回false。 $timeout是以秒为单位的超时时间,$con_per_sec是每秒连接尝试的次数。
测试在Windows和Linux,PHP的5.5.x

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