I have websocket server written in native php. I run the server in linux's screen.
It works fine. client can connect to the webserver. but after a few days (not sure how many days, happen randomly), the websocket are not accepting new connection anymore.
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.'
');
}
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.'
');
}
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.'
');
}
/**
* 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.'
');
}
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.'
');
}
unset($clientSockets[$socket_index]);
if(isset($socketLists[$socket_list_index])){
unset($socketLists[$socket_list_index]);
}
}
}
}
It always stop at error_log('Websocket new connection before read header');
I expect if there is an error, it will show here error_log('Could not read on new_client_socket: ['.$error_code.'] '.$error_msg.'
');
But no error came out. It just stuck there.
If i try to connect to the websocket, i check netstat -tcp
in server, it shows state Established
.
the status:-
tcp 0 0 roomie-devel:cslistener internettl.org:51715 ESTABLISHED 17556/php
please someone help me, is there any settings in linux that i need to change?
i try socket_close, but it return error:-
error disconnect socket_close: [104] Connection reset by peer
there's also error in socket_getpeername() and another socket_close() error:-
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
error disconnect socket_close: [107] Transport endpoint is not connected
based on my research, to close tcp connection, both end need to send close connection request. but you cannot called the socket_close if client is unexpectedly close their connection (for eg: they force shutdown their computer). how do i properly close connection for this situation? do i need to set anything in linux to close any socket not properly close?