我正在使用PHP阻止套接字,并且遇到了一个奇怪的问题。
最近,很少有用户将其websocket服务器随机挂起。 我设法发现这是由客户端的网络故障(过载/不稳定或计算机性能低下)引起的。
我终于能够使用Clumsy重现该错误,模拟数据包丢失,滞后,节流等问题,迫使客户端随机重新连接。 数小时的日志调查之后,似乎永远占据了上风:
// Note : $this->socket is a blocking TLS socket (resource type : stream)
$new = stream_socket_accept( $this->socket, 2 );
套接字元数据(由stream_get_meta_data($ this-> socket)返回):
array(
'stream_type' => 'tcp_socket/ssl',
'mode' => 'r+',
'unread_bytes' => 0,
'seekable' => false,
'timed_out' => false,
'blocked' => true,
'eof' => true,
)
此行在processMasterSocket()中,在此处调用:
stream_select( $read, $w = null, $e = null, $this->options['timeout_select'], $this->options['timeout_select_microsec'] );
foreach( $read as $socket )
{
if( $socket == $this->socket->getResource() )
$this->processMasterSocket();
else
$this->processClientSocket( $socket );
}
问题在于stream_socket_accept()
要么花费0.0003s,200.0s,要么永远!
我已经阅读了有关阻止套接字怪异行为的信息,但是到目前为止,我们无法切换到非阻止模式(因为这将需要完全重写我们的TLS /安全代码)。 同样,不启用糟糕的网络模拟器也没有问题。
这是我的问题:
为什么stream_socket_accept()
有时需要花费很长的时间,而完全忽略了参数中给出的2s超时?
如果它正在等待数据(由于阻止模式),为什么stream_select()
告诉我有些东西要读?
stream_select()
可以在丢包时正确地与阻塞套接字一起工作吗?
stream_socket_accept()
是否有阻止套接字超时的方法?
答案 0 :(得分:1)
发现该问题与PHP本身有关。 我忘了提到我正在运行PHP 5.3.3,而我刚遇到了这个https://bugs.php.net/bug.php?id=41631
PHP 5.4.33中修复了有关SSL阻止套接字不超时的问题
我刚刚在PHP 7.x上尝试了我的代码,它运行流畅,在60秒后超时(这是default_socket_timeout值)。
真的希望这会有所帮助,即使大多数人应该已经升级到PHP 7.x了;)