У меня есть сервер websocket, написанный на нативном php.Я запускаю сервер на экране linux.
Работает нормально.Клиент может подключиться к веб-серверу.но через несколько дней (не знаю, сколько дней произойдет случайно) веб-сокет больше не принимает новое соединение.
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');
Но ошибки не вышло.Он просто застрял там.
Если я пытаюсь подключиться к веб-сокету, я проверяю 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, чтобы закрыть сокет, который не был правильно закрыт?