На nix сервере постоянно запущен php скрипт, принимающий данные через Интернет от удаленных датчиков по GPRS/EDGE каждые несколько секунд.
В Сети нашлось множество примеров работы с сокетами в php однако у всех них общий недостаток — через несколько десятков минут непрерывной работы скрипт «зависает» и сокеты порожденные им висят в статусе FIN_WAIT_1.
Я временно решил данную проблему установив режим сокета в неблокирующий режим и включив SO_LINGER ('l_onoff'=>1, 'l_linger'=>0), т.е. грубо закрываю сокет не дожидаясь ответа после получения данных.
Однако данная мера вызывает реконнект дорогостоящего GPRS соединения ибо операторы округляют трафик по 100кб обычно, т.е. факт соединения уже 100кб считай утекло. Хотелось бы увидеть реально рабочий пример как можно НЕ разрывая соединения стабильно принимать данные от датчиков и при этом не вызывать «зависание» сокетов и самого скрипта.
Ниже привожу часть кода с учетом моих поправок по приему данных на PHP:
$socket = socket_create_listen($port, SOMAXCONN) ;
socket_set_nonblock($socket);
$arrOpt = array('l_onoff'=>1, 'l_linger'=>0);
while(1) {
usleep(100000);
if((time()-$time) >= 60) { $time = time(); UpdatePID($pid); }
$client = @socket_accept($socket);
if(!$client) continue;
socket_set_option($client, SOL_SOCKET, SO_LINGER, $arrOpt);
$data = socket_read($client, 4096);
$data = trim($data);
Save2DB($data);
socket_close($client);
if(strtolower($input)=="exit") break; }
socket_close($socket);
UpdatePID — обновляет pid файл, необходимый для предотвращения повторного запуска скрипта.
Save2DB — парсит и пишет данные в базу.
С использованием socket_set_option(..SO_KEEPALIVE...) никто не работал?