Я получаю пакеты, отправленные на мой сервер через UDP. Я использую socket_read для чтения данных, и он идет хорошо. Однако я столкнулся с ошибкой. Параметр длины для socket_read в моем случае НЕ всегда один и тот же. Длина данных может варьироваться от 50 до 150 байтов. Единственное, что остается постоянным, это то, что набор данных заканчивается байтом \ x00. Как бы я мог прочитать функцию чтения, которая всегда читается до тех пор, пока не встретит этот байт? Я уже пробовал флаг PHP_NORMAL_READ, но документы говорят, что это заканчивается только в \ n или \ r, что действительно не то, что я хочу (попробовал, он не работает для моих данных). В то же время, php-страница для socket_read заявляет в описании параметра длины, который,
Максимальное количество прочитанных байтов задается параметром длины. В противном случае вы можете использовать \ r, \ n или \ 0 для завершения чтения (в зависимости от параметра типа, см. Ниже).
Тип ничего не говорит о байте / 0. Его, как часть документации, отсутствует. Мне нужна функция, которая позволит мне указать разделитель для моих данных, автоматически прочитает все данные из имеющегося сокета. Может быть решение в функции socket_recv, но его недокументировано, и я не знаю, как это работает.
Заранее спасибо.
Если я правильно понимаю, вы хотите прочитать данные из сокета до тех пор, пока не будет больше данных для чтения, при этом проблема состоит в том, что объем данных является переменным, и вы не знаете, когда остановиться.
Согласно соответствующей странице руководства ( http://php.net/socket_read ):
Примечание: socket_read () возвращает строку нулевой длины (""), когда больше нет данных для чтения.
Вы должны иметь возможность обрабатывать данные переменной длины, читая побайтовые байты, пока не нажмете строку нулевой длины:
while (($currentByte = socket_read($socket, 1)) != "") { // Do whatever you wish with the current byte }
Приложение, использующее считываемую полезную нагрузку, должно будет узнать, когда вы достигли «конца записи» для любого передаваемого сообщения приложения. Ожидайте произвольную длину при чтении.
Будьте осторожны с использованием UDP, так как вы не можете гарантировать, что порядок чтения пакетов – это порядок, отправленный одноранговым узлом, если вы пытаетесь передать несколько сообщений в сообщение. Рекомендуем использовать сокет TCP в этом случае.
Вы попробовали что-то вроде этого:
do { echo socket_read($handle,1024); $status = socket_get_status($handle); } while($status['unread_bytes']);
Применил другой подход, который может работать только в вашем случае:
<?php function tftp_fetch($host, $filename) { $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); // create the request packet $packet = chr(0) . chr(1) . $filename . chr(0) . 'octet' . chr(0); // UDP is connectionless, so we just send on it. socket_sendto($socket, $packet, strlen($packet), 0x100, $host, 69); $buffer = ''; $port = ''; $ret = ''; do { // $buffer and $port both come back with information for the ack // 516 = 4 bytes for the header + 512 bytes of data socket_recvfrom($socket, $buffer, 516, 0, $host, $port); // add the block number from the data packet to the ack packet $packet = chr(0) . chr(4) . substr($buffer, 2, 2); // send ack socket_sendto($socket, $packet, strlen($packet), 0, $host, $port); // append the data to the return variable // for large files this function should take a file handle as an arg $ret .= substr($buffer, 4); } while(strlen($buffer) == 516); // the first non-full packet is the last. return $ret; } ?>
Наиболее интересная часть этого подхода:
do ... while(strlen($buffer) == 516); // the first non-full packet is the last.