Сервер сокетов PHP, проверьте, жив ли клиент - PullRequest
3 голосов
/ 20 марта 2012

У меня есть php-сервер, который прослушивает 1 клиент c #.

Когда соединение установлено, оно сохраняется до тех пор, пока клиент не отправит команду "quit", которая убьет сервер PHP.

Нокогда клиент c # отключается без команды «quit» (т. е. нажатием кнопки «закрыть» (x) в форме окна), сервер просто продолжает слушать и не может получить любое другое соединение от этого клиента.

Есть лиспособ проверить со стороны сервера (PHP), что соединение с клиентом все еще живо.

Код моего php-сервера основан на примере 1: http://php.net/manual/en/sockets.examples.php

Если кто-то заинтересован в воспроизведенииповедение ошибки / ошибки, вставьте код из example1: http://php.net/manual/en/sockets.examples.php, подключитесь по telnet с удаленного клиента в локальной сети, отключите клиентский провод ... php-сервер будет зависать вечно, новое подключение не будет принято

(простите за мой плохой английский)

Ответы [ 3 ]

2 голосов
/ 20 марта 2012

В вашем цикле вам нужно проверить возвращаемое значение socket_read(). Если он возвращает FALSE, то произошла ошибка чтения (которая может быть вызвана удаленным хостом, закрывающим соединение). Пример кода в предоставленной вами ссылке охватывает этот случай.

Если вам необходимо корректно обработать определенные состояния ошибок, вы всегда можете проверить код ошибки сокета, используя socket_last_error() - в этой заметке описаны возможные коды.

Изменить:

При использовании замазки для telnet, если я закрываюсь с помощью кнопки X, соединение в PHP корректно закрывается, но если я отсоединяю провод Ethernet от машины замазки, PHP-сервер просто зависает.

Причина, по которой соединение закрывается при уничтожении PuTTY, заключается в том, что PuTTY закрывает свои открытые соединения при выходе. Это приводит к тому, что socket_read() возвращается с кодом ошибки (я считаю ECONNRESET). Если вы потянете сетевой кабель, у него не будет возможности сделать это.

В зависимости от того, как настроена ваша сеть, TCP-соединение должно со временем прерваться. Вы можете попытаться контролировать время ожидания, установив SO_RCVTIMEO с помощью socket_set_option(), но это не всегда работает на всех платформах (я смотрю на вас, WinSock) .

В качестве альтернативы, вы можете свернуть свой собственный цикл опроса, используя socket_select() с разумным временем ожидания. Если ни один из подключенных сокетов не имеет данных для отправки после истечения времени ожидания, уничтожьте сервер.

0 голосов
/ 24 января 2017

Я сделал это, проверив, содержит ли массив socket_select() $read рассматриваемое соединение, но данные socket_read() пусты (дважды).

Похоже, что socket_select() добавляет отключенных клиентов в массив $read, а socket_read() выдает пустую строку '' при попытке прочитать данные отключенного клиента.

0 голосов
/ 19 июля 2016

Следующий код покажет состояние соединения.

<code>  $address='example.com';
    $port = '9065';
    if (isset($port) && ($socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP))
     && (socket_connect($socket, $address, $port)))  {
    $text='Connection successful on IP $address, port $port';
    socket_close($socket);
    }
    else  {
    $text='Unable to connect<pre>'.socket_strerror(socket_last_error()).'
'; } echo $ text;
...