У меня странная проблема с библиотекой сокетов 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).
Хорошо, я полагаю, что я мог бы также превратить комментарии выше в ответ. Вся заслуга Райана Винсента за то, что он помог моей толстой голове разобраться в этом 🙂
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).
}
У меня странная проблема с библиотекой сокетов 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).
Хорошо, я полагаю, что я мог бы также превратить комментарии выше в ответ. Вся заслуга Райана Винсента за то, что он помог моей толстой голове разобраться в этом 🙂
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).
}