Как узнать размер данных полученного пакета udp

Я разработал небольшой сервер UDP с php

<?php
$socket = stream_socket_server("udp://0.0.0.0:1201", $errno, $errstr, STREAM_SERVER_BIND);
if (!$socket) {
die("$errstr ($errno)");
}

do {
$pkt = stream_socket_recvfrom($socket, 1, 0, $peer);
echo "$peer\n";
} while ($pkt !== false);

?>

Я хочу напечатать размер данных каждого полученного пакета, а также порт источника и порт назначения.

Как я могу это сделать?

1

Решение

Если вы используете сокет, который был создан для UDP, то возвращаемое значение функции приема — это размер пакета. Я посмотрел пример кода, но затем специально для PHP:

do {
$pkt = stream_socket_recvfrom($socket, 1, 0, $peer);
echo "$peer\n";
stream_socket_sendto($socket, date("D M j H:i:s Y\r\n"), 0, $peer);
} while ($pkt !== false);

это, как я и ожидал: возвращаемое значение функции приема $ pkt — это размер полученного пакета, тогда как $ peer — это содержимое того, что получено.

Если вы напечатаете значение $ pkt, вы увидите, что оно содержит размер пакета.

Размеры пакетов в UDP имеют значение для приложения. Если вы используете UDP и отправляете 2050 байтов, если пакет не теряется, вы точно получите эти 2050 байтов на приемнике. Таким образом, в этом нет необходимости и даже невозможно получить доступ к заголовку UDP в нормальных условиях. Нет необходимости идти в сырой сокет либо.
Размеры пакетов, которые могут быть отправлены UDP, в основном ограничены по размеру IP. (64k) Поскольку IP собирается фрагментировать пакет во время отправки и выполнять дефрагментацию на принимающей стороне. фрагменты могут быть получены не по порядку и тому подобное. IP просто объединяет их.

Чтобы избежать путаницы, я имею в виду размер пакета, который пользователь отправляет и получает в качестве полезной нагрузки для UDP.

ссылка string stream_socket_recvfrom ( resource $socket , int $length [, int $flags = 0 [, string &$address ]] )
от http://php.net/manual/en/function.stream-socket-recvfrom.php

показывает, что вы можете получить адрес того, кто отправляет вам также.

1

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

Ваш код не работает на уровне udp, то есть само сообщение udp будет обрабатываться ядром. Вы работаете на уровне приложения, вы просто получаете данные. Если данные фрагментированы по нескольким пакетам обновлений, вы этого не заметите. Это сделано в стеке OSI.

Если вы общаетесь на уровне UDP, вы можете получить размер каждого пакета в заголовке UDP. Вам нужно будет использовать сырые розетки для этого. Но я думаю, что это было бы интересно только в образовательных целях.

Обычно код приложения не заботится о размере отдельных пакетов UDP, но заботится о размере сообщение. Формат сообщения определяется в протоколе приложения верхнего уровня. HTTP определяет Content-Length заголовок например.

0