php - Websocket 服务器不允许来自客户端的新连接,卡在 socket_read(没有错误)
问题描述
我有用本机 php 编写的 websocket 服务器。我在 linux 的屏幕上运行服务器。
它工作正常。客户端可以连接到网络服务器。但几天后(不确定多少天,随机发生),websocket 不再接受新连接。
set_time_limit(0);
if(!($socket = socket_create(AF_INET, SOCK_STREAM, 0))){
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
die();
}
if(!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)){
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
die();
}
if(!socket_bind($socket, 0, $port)){
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
die();
}
if(!socket_listen($socket))
{
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
die();
}
/**
* array of client sockets
**/
$clientSockets = array($socket);
$socketLists = array();
$write = null;
$except = null;
$header = array();
/**
* start endless loop, so that our script doesn't stop
**/
while (true) {
/**
* array of sockets to read
* !get from clientSockets array
**/
$readSockets = $clientSockets;
/**
* now call select - blocking call
**/
if(socket_select($readSockets , $write , $except , 0, 10) === false)
{
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
error_log('Could not listen on socket: ['.$error_code.'] '.$error_msg.'\n');
}
if(in_array($socket, $readSockets)){
/**
* Accept new client socket
**/
if(($new_client_socket = socket_accept($socket)) !== false){
error_log('Websocket has new connection');
/**
* Add new client socket to client socket array
**/
$clientSockets[] = $new_client_socket;
/**
* read data sent by the socket buffer(65536, 65536)
**/
error_log('Websocket new connection before read header');
if(!($header = socket_read($new_client_socket, 65536))){
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
error_log('Could not read on new_client_socket: ['.$error_code.'] '.$error_msg.'\n');
}
error_log('Websocket new connection after read header => '.json_encode($header));
$datas = json_decode($header);
if ((isset($datas->type) && $datas->type == "server") || (isset($datas->type) && $datas->type == "cec")) {
$newDatas = json_decode($datas->data);
$searchIndex = strtolower($newDatas->ip_address) . '-' . strtolower($newDatas->mac_address);
unset($datas->type);
$response = mask(json_encode($datas));
checkSocketAndSendMessage($clientSockets, $socketLists, $searchIndex, $response);
}else{
performHandshaking($header, $new_client_socket, $host, $port);
}
/**
* make room for new socket
**/
$found_socket = array_search($socket, readSockets);
unset($readSockets[$found_socket]);
}else{
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
// die();
}
}
foreach ($readSockets as $readSocket) {
$buf = @socket_read($readSocket, 65536, PHP_NORMAL_READ);
if(strlen($buf) < 1){
$socket_index = array_search($readSocket, $clientSockets);
$socket_list_index = '';
foreach($socketLists as $key => $socketList){
if($readSocket == $socketList['index']){
$socket_list_index = $key;
}
}
if(!socket_getpeername($readSocket, $ip)){
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
error_log('error disconnect socket_getpeername: ['.$error_code.'] '.$error_msg.'\n');
}
/**
* Added to try cater
* CLOSE_WAIT problem
**/
$linger = array ('l_linger' => 0, 'l_onoff' => 1);
if(!socket_set_option($clientSockets[$socket_index], SOL_SOCKET, SO_LINGER, $linger)){
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
error_log('error disconnect socket_set_option: ['.$error_code.'] '.$error_msg.'\n');
}
if(!socket_close($clientSockets[$socket_index])){
$error_code = socket_last_error();
$error_msg = socket_strerror($error_code);
error_log('error disconnect socket_close: ['.$error_code.'] '.$error_msg.'\n');
}
unset($clientSockets[$socket_index]);
if(isset($socketLists[$socket_list_index])){
unset($socketLists[$socket_list_index]);
}
}
}
}
它总是停在error_log('Websocket new connection before read header');
我希望如果有错误,它会显示在这里error_log('Could not read on new_client_socket: ['.$error_code.'] '.$error_msg.'\n');
但是没有出现错误。它只是卡在那里。
如果我尝试连接到 websocket,我检查netstat -tcp
服务器,它显示状态Established
。
状态:-
tcp 0 0 roomie-devel:cslistener internettl.org:51715 ESTABLISHED 17556/php
请有人帮助我,我需要更改linux中的任何设置吗?
我尝试socket_close,但它返回错误: -
error disconnect socket_close: [104] Connection reset by peer\n
socket_getpeername() 和另一个 socket_close() 错误中也有错误:-
PHP Warning: socket_getpeername(): unable to retrieve peer name [107]: Transport endpoint is not connected in /var/www/html/webSocket/webSocket.php on line 296
error disconnect socket_getpeername: [107] Transport endpoint is not connected\n
error disconnect socket_close: [107] Transport endpoint is not connected\n
根据我的研究,要关闭 tcp 连接,两端都需要发送关闭连接请求。但是如果客户端意外关闭他们的连接(例如:他们强制关闭他们的计算机),你不能调用 socket_close。对于这种情况,我该如何正确关闭连接?我是否需要在 linux 中设置任何内容来关闭任何未正确关闭的套接字?
解决方案
推荐阅读
- mysql - Laravel mongodb 查询原始数据
- freeswitch - freeswitch 在呼叫呼叫中心的代理期间至少 60 秒无法接收 b-leg dtmf
- android - 在 robolectric 的测试中使用 hiltViewModel() 和 createComposeRule() 会抛出 NoSuchMethodException
- swift - 自定义 UICollectionViewLayout 中的自定义标题
- angularjs - Angular - 具有链接 href 的复杂路由器参数的解决方案
- php - Laravel 重置密码控制器及功能
- android - 在我的 RecyclerView 中实现分页后,图像未显示
- security - 为什么 x86 允许未对齐的访问,以及如何检测未对齐的访问?
- azure-eventgrid - 将消息而不是事件放入 Azure 事件网格
- html - iOS Voice Over 和 Android 无法在 Span 标签中宣布文本