gpt4 book ai didi

PHP stream_socket_accept 因阻塞 TLS 套接字而挂起

转载 作者:行者123 更新时间:2023-12-03 11:53:46 26 4
gpt4 key购买 nike

我在 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() 有时需要永远,完全忽略参数中给定的 2 秒超时?

  • 如果它正在等待数据(因为阻塞模式),为什么 stream_select() 告诉我有东西要读取?

  • 当有一些数据包丢失时,stream_select() 是否可以正确处理阻塞套接字?

  • 有没有办法让 stream_socket_accept() 因阻塞套接字而超时?

最佳答案

发现问题与PHP本身有关。我忘了说我正在运行 PHP 5.3.3,我刚遇到这个 https://bugs.php.net/bug.php?id=41631

PHP 5.4.33 修复了 SSL blocking sockets 不超时的问题

我刚刚在 PHP 7.x 上尝试了我的代码,它运行顺利,在 60 秒后超时(这是 default_socket_timeout 值)。

真的希望这会有所帮助,即使大多数人应该已经升级到 PHP 7.x ;)

关于PHP stream_socket_accept 因阻塞 TLS 套接字而挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51171398/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com