Обнаружение разрыва соединения (EOF) с модулем сокета PHP

У меня странная проблема с библиотекой сокетов PHP: мне кажется, что я не могу обнаружить / различить EOF сервера, и в результате мой код беспомощно заходит в бесконечный цикл.

Дальнейшее объяснение ниже; Прежде всего, некоторый контекст (здесь нет ничего особенного):

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 8081);

for (;;) {

$read = [$socket];
$except = NULL;
$write = [];

print "Select <";
$n = socket_select($read, $write, $except, NULL);
print ">\n";

if (count($read)) {

print "New data: ";

#socket_recv($socket, $data, 1024, NULL);
$data = socket_read($socket, 1024);

print $data."\n";

}

print "Socket status: ".socket_strerror(socket_last_error())."\n";

}

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

Для тестирования я сейчас использую ncat -vvklp 8081 связать сокет и быть сервером. С этим запуском я могу запустить приведенный выше код, и он подключается и работает — например, я могу набрать ncat окно, и PHP получает его. (Отправка данных из PHP тоже работает, но я исключил этот код, так как он не актуален.)

Тем не менее, момент, когда я ^C ncatприведенный выше код входит в жесткий бесконечный цикл — и PHP говорит, что в сокете нет ошибок.

Я пытаюсь выяснить, где находится кнопка, которая бьет PHP головой вверх и заставляет его понять, что узел отключился.

  • socket_get_status() это большой неверный — это псевдоним для stream_get_meta_data()и на самом деле это не работает на сокетах!

  • feof() так же носики Warning: feof(): supplied resource is not a valid stream resource,

Я не могу найти socket_* функция для обнаружения одноранговой EOF.

Одна из инструкций по PHP для socket_read() первоначально отговорил меня от использования этой функции, поэтому я использовал socket_recv() вместо этого, но я в конце концов попробовал это на всякий случай — но без игры в кости; переключение на прием вызова не имеет никакого эффекта.

я иметь обнаружил, что наблюдение за сокетом для записи, а затем попытка записи в него внезапно заставит PHP перейти «о, подождите, правильно» и начать возвращаться Broken pipe — но мне не интересно писать на сервер, я хочу читать с него!

Наконец, что касается комментируемой части — я бы далеко предпочитаю использовать встроенную функциональность потока PHP, но stream_* функции не предоставляют никаких средств для обработки асинхронных событий подключения (что я хочу сделать, так как я делаю несколько подключений). я могу сделать stream_socket_client(... STREAM_CLIENT_ASYNC_CONNECT ...) но потом не могу узнать когда соединение было установлено (6-летняя ошибка PHP # 52811).

5

Решение

Хорошо, я полагаю, что я мог бы также превратить комментарии выше в ответ. Вся заслуга Райана Винсента за то, что он помог моей толстой голове разобраться в этом 🙂

socket_recv вернусь 0 в частности, если узел отключился, или FALSE если любая другая ошибка сети произошло.

Для справки, в C, recv()возвращаемое значение — это длина новых данных, которые вы только что получили (которые могут быть 0), или же -1 указать состояние ошибки (значение которого можно найти в errno).

С помощью 0 указание условия ошибки (и только одного произвольного типа условия ошибки, в этом случае) не является стандартным и уникальным для PHP всеми неправильными способами. Другие сетевые библиотеки не работают таким образом.

Вы должны справиться с этим, как это.

$r = socket_recv($socket, $buf, $len);

if ($r === FALSE) {

// Find out what just happened with socket_last_error()
// (there's a great list of error codes in the comments at
// http://php.net/socket_last_error - considering/researching
// the ramifications of each condition is recommended)

} elseif ($r === 0) {

// The peer closed the connection. You need to handle this
// condition and clean up.

} else {

// You DO have data at this point.
// While unlikely, it's possible the remote peer has
// sent you data of 0 length; remember to use strlen($buf).

}
1

Другие решения

У меня странная проблема с библиотекой сокетов PHP: мне кажется, что я не могу обнаружить / различить EOF сервера, и в результате мой код беспомощно заходит в бесконечный цикл.

Дальнейшее объяснение ниже; Прежде всего, некоторый контекст (здесь нет ничего особенного):

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 8081);

for (;;) {

$read = [$socket];
$except = NULL;
$write = [];

print "Select <";
$n = socket_select($read, $write, $except, NULL);
print ">\n";

if (count($read)) {

print "New data: ";

#socket_recv($socket, $data, 1024, NULL);
$data = socket_read($socket, 1024);

print $data."\n";

}

print "Socket status: ".socket_strerror(socket_last_error())."\n";

}

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

Для тестирования я сейчас использую ncat -vvklp 8081 связать сокет и быть сервером. С этим запуском я могу запустить приведенный выше код, и он подключается и работает — например, я могу набрать ncat окно, и PHP получает его. (Отправка данных из PHP тоже работает, но я исключил этот код, так как он не актуален.)

Тем не менее, момент, когда я ^C ncatприведенный выше код входит в жесткий бесконечный цикл — и PHP говорит, что в сокете нет ошибок.

Я пытаюсь выяснить, где находится кнопка, которая бьет PHP головой вверх и заставляет его понять, что узел отключился.

  • socket_get_status() это большой неверный — это псевдоним для stream_get_meta_data()и на самом деле это не работает на сокетах!

  • feof() так же носики Warning: feof(): supplied resource is not a valid stream resource,

Я не могу найти socket_* функция для обнаружения одноранговой EOF.

Одна из инструкций по PHP для socket_read() первоначально отговорил меня от использования этой функции, поэтому я использовал socket_recv() вместо этого, но я в конце концов попробовал это на всякий случай — но без игры в кости; переключение на прием вызова не имеет никакого эффекта.

я иметь обнаружил, что наблюдение за сокетом для записи, а затем попытка записи в него внезапно заставит PHP перейти «о, подождите, правильно» и начать возвращаться Broken pipe — но мне не интересно писать на сервер, я хочу читать с него!

Наконец, что касается комментируемой части — я бы далеко предпочитаю использовать встроенную функциональность потока PHP, но stream_* функции не предоставляют никаких средств для обработки асинхронных событий подключения (что я хочу сделать, так как я делаю несколько подключений). я могу сделать stream_socket_client(... STREAM_CLIENT_ASYNC_CONNECT ...) но потом не могу узнать когда соединение было установлено (6-летняя ошибка PHP # 52811).

5

Хорошо, я полагаю, что я мог бы также превратить комментарии выше в ответ. Вся заслуга Райана Винсента за то, что он помог моей толстой голове разобраться в этом 🙂

socket_recv вернусь 0 в частности, если узел отключился, или FALSE если любая другая ошибка сети произошло.

Для справки, в C, recv()возвращаемое значение — это длина новых данных, которые вы только что получили (которые могут быть 0), или же -1 указать состояние ошибки (значение которого можно найти в errno).

С помощью 0 указание условия ошибки (и только одного произвольного типа условия ошибки, в этом случае) не является стандартным и уникальным для PHP всеми неправильными способами. Другие сетевые библиотеки не работают таким образом.

Вы должны справиться с этим, как это.

$r = socket_recv($socket, $buf, $len);

if ($r === FALSE) {

// Find out what just happened with socket_last_error()
// (there's a great list of error codes in the comments at
// http://php.net/socket_last_error - considering/researching
// the ramifications of each condition is recommended)

} elseif ($r === 0) {

// The peer closed the connection. You need to handle this
// condition and clean up.

} else {

// You DO have data at this point.
// While unlikely, it's possible the remote peer has
// sent you data of 0 length; remember to use strlen($buf).

}

active «data-shortcut =» A
самый старый «data-shortcut =» O
голосует «data-shortcut =» V
1
По вопросам рекламы [email protected]