2012-03-20 2 views
2

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

Когда соединение установлено, оно сохраняется в живых до тех пор, пока клиентская команда «quit» не уничтожит сервер PHP.

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

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

Мой код PHP сервер основан на exemple1 из: http://php.net/manual/en/sockets.examples.php

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

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

ответ

2

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

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

Edit:

При использовании шпаклевки для телнет, если я закрыть с помощью кнопки X, connecion правильно закрыта в PHP, но если я отключить сетевой провод из замазки машины, PHP сервер просто зависает вокруг.

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

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

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

+0

больше обновлений. При использовании шпатлевки для telnet, если я закрываю кнопку X, соединение закрывается должным образом на PHP, но если я отключу провод ethernet машины-замазки, сервер PHP просто зависает. –

+0

@Vincemcman: Обновлен ответ в ответ на ваш комментарий. –

+0

Когда вы нажимаете кнопку X на замазке, которая запускает событие закрытия или выключения с соединением, если вы преждевременно отключены, он так и не получил ответ, поэтому он ожидает, что в ближайшее время будет отправлено больше данных. – OpensaurusRex

0

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

$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()).'</pre>'; 
    } 
    echo $text; 
0

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

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

Смежные вопросы