За последние 24 часа нас посетили 20847 программистов и 1626 роботов. Сейчас ищут 837 программистов ...

PHP сокеты. Проблема с таймаутом

Тема в разделе "Прочие вопросы по PHP", создана пользователем Nikita92, 27 сен 2015.

  1. Nikita92

    Nikita92 Новичок

    С нами с:
    27 сен 2015
    Сообщения:
    5
    Симпатии:
    0
    Всем доброго времени суток. Пожалуйста, помоги разобраться с проблемой.

    Я написал небольшой чат с использованием WebSockets и самописным сервером на php без использования phpDaemon, Libevent и прочих подобных вещей. Всё работает как надо, кроме одной детали: остаётся много зависших коннектов. При закрытии браузера или вкладки клиент отключается правильно, но если у пользователя, например, пропадает соединение с интернетом, то коннект остаётся висеть на сервере ещё ровно 20 минут. Никак не могу понять в чем проблема. Возможно в функции stream_socket_accept? Я перепробовал все возможные значения таймаута, но ничего не меняется. Может есть какая-то настройка PHP, о которой я не знаю?

    Вот кусок кода сервера:

    Код (PHP):
    1. $socket = stream_socket_server("tcp://0.0.0.0:8080", $errno, $errstr);
    2.  
    3. $this->stop_server = false;
    4. $this->connects = array();
    5. $this->sites = array();
    6.  
    7. while($this->stop_server == false){
    8.  
    9.     //Формируем массив прослушиваемых сокетов
    10.     $read = $this->connects;
    11.     $read[]= $socket;
    12.     $write = $except = null;
    13.  
    14.     if(!stream_select($read, $write, $except, null)){
    15.         break;
    16.     }
    17.  
    18.     if(in_array($socket, $read)){
    19.         if(($connect = stream_socket_accept($socket, -1)) && $info = $this->handshake($connect)){
    20.             $this->connects[] = $connect;
    21.             $this->on_open($connect, $info);
    22.         }
    23.         unset($read[array_search($socket, $read)]);
    24.     }
    25.  
    26.     //Обрабатываем все соединения
    27.     foreach($read as $connect){
    28.     
    29.         $data = fread($connect, 1024);
    30.         
    31.         $disconnect = false;
    32.         
    33.         if(!$data || strlen($data) === 0){
    34.             $disconnect = true;
    35.         } else {
    36.             $data = $this->decode($data);
    37.             if($data['type'] == 'close'){
    38.                 $disconnect = true;
    39.             }    
    40.         }
    41.  
    42.         if($disconnect == true){
    43.             //Соединение было закрыто
    44.             $this->disconnect_client($connect);
    45.             continue;
    46.         }                    
    47.  
    48.     }
    49.  
    50. }
    51.  
    PHP, JavaScript, SQL и другой код пишите внутри тегов
    Код ( (Unknown Language)):
    1. [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
     
  2. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    На сокет можно ставить таймаут чтения данных и еще некоторые таймауты
    Код (Text):
    1.  
    2. $timeout = array('sec'=>1,'usec'=>500000);
    3. socket_set_option($socket,SOL_SOCKET,SO_RCVTIMEO,$timeout);
    http://php.ru/manual/function.socket-set-option.html
     
  3. Nikita92

    Nikita92 Новичок

    С нами с:
    27 сен 2015
    Сообщения:
    5
    Симпатии:
    0
    Не получается. Эта функция работает только с socket_create, а у меня stream_socket_server. Или я что-то не так понял?
    Выдаёт вот это: Warning: socket_set_option(): supplied resource is not a valid Socket resource
     
  4. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Точно. Зато у функции stream_select(), которую ты используешь, последние необязательные параметры это таймаут.
     
  5. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
  6. Nikita92

    Nikita92 Новичок

    С нами с:
    27 сен 2015
    Сообщения:
    5
    Симпатии:
    0
    У stream_select ставил таймаут и при этом сервер останавливается. А мне нужно чтобы отключался только один зависший коннект.
    stream_set_timeout тоже не работает
     
  7. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Сервер не может знать, что клиент завис. Когда клиент зависает, он ничего не сообщает серверу, следовательно сервер не сможет узнать, что он завис. Поэтому единственным верным решением является таймаут. Например ты можешь поставить таймаут в 5 секунд, и при разработке клиента позаботится, чтобы он посылал хоть что нибудь на каждые 4 секунды.
     
  8. Nikita92

    Nikita92 Новичок

    С нами с:
    27 сен 2015
    Сообщения:
    5
    Симпатии:
    0
    В том то и проблема, что у меня не получается поставить таймаут. Я что только не пробовал.. Соединение рвется только через 20 минут. Нигде не могу уменьшить это значение хотябы до 1 минуты