чтение частично из сокетов - PullRequest
9 голосов
/ 18 июня 2010

У меня есть небольшая тестовая программа, которая отправляет много пакетов udp между клиентом-> сервером-> клиентом (тест ping / pong).Пакеты имеют фиксированный размер при каждом запуске (последний запуск - максимально допустимый размер пакета udp). Я заполняю пакеты случайными данными, за исключением начала каждого пакета, который содержит номер пакета.Так что мне интересно только посмотреть, получу ли я все пакеты обратно на клиент.

Я использую sendto () и recvfrom (), и я читаю только sizeof (packet_number) (который в данном случае является int).Что происходит с остальными данными?Это заканчивается в сказочной стране (сбрасывается)?или новый пакет, который прибывает, добавляется к этим "старым" данным?

(используя linux)

Ответы [ 3 ]

14 голосов
/ 18 июня 2010

Каждое чтение из очереди сокетов UDP одна целая дейтаграмма вне буфера получения сокета ядра независимо от размера буфера в вашей пользовательской области.То есть:

  • Если ваш буфер больше, чем следующая ожидающая датаграмма, вы будете читать меньше, чем размер вашего буфера.
  • Если ваш буфер меньше, вы будете читатьразмер буфера, а остальные данные отбрасываются.
  • Вы можете установить опцию MSG_TRUNC в flags, поэтому recv(2) будет возвращать всю длину дейтаграммы, а не толькочасть, которую вы читаете в свой пользовательский буфер.

Надеюсь, это поможет.

5 голосов
/ 18 июня 2010

Чтобы ответить на ваш первый вопрос, отбрасываются ли данные? Да, это так. Протоколы IP и ARP вступают в игру, когда ваш пакет больше, чем Path MTU. Path MTU - это максимальная единица передачи пути между вашим клиентом и сервером. Предполагая, что ваша сетевая карта является стандартной сетевой картой, максимальный MTU равен 1500. Теперь давайте предположим, что MTU всего пути между вашим клиентом и сервером составляет 1500. В этом сценарии вы отправляете любой пакет, размер которого превышает 1472 байта. (1500 - (20-байтовый заголовок ip) - (8-байтовый заголовок UDP)) тогда произойдет фрагментация IP. Затем произойдет то, что уровень IP будет разбивать пакет на фрагменты для соответствия MTU канала Ethernet. Теперь, прежде чем какие-либо данные могут быть отправлены, необходимо разрешить MAC-адрес получателя. Таким образом, внезапно, протокол ARP получит несколько фрагментов IP, запрашивающих разрешение одного и того же IP-адреса MAC. Затем произойдет то, что ARP будет инициировать запрос ARP для первого принятого пакета и ждать ответа ARP. Во время ожидания ARP отбрасывает все фрагменты, выполняющие один и тот же запрос ARP, и ставит в очередь только последний поступивший фрагмент. Поэтому, если вы отправляете пакет размером более 1472 байт, не ожидайте получения всего пакета на другом конце, если ваш кэш ARP пуст.

Добавляется ли вновь поступивший пакет к Нет, это не добавляется. UDP - это протокол дейтаграмм со строгими границами сообщений. Таким образом, каждый поступающий пакет считается полной автономной дейтаграммой; данные не будут добавлены.

3 голосов
/ 18 июня 2010

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

Существует два способа обнаружения усечения:

Используйте флаг MSG_TRUNC. recvfrom вернет истинный размер пакета, даже если он не уместился в предоставленном буфере. Таким образом, вы можете просто проверить, больше ли возвращаемое значение, чем len, которое вы указали в качестве аргумента.

Используйте recvmsg и проверьте возвращенную структуру на наличие флага MSG_TRUNC.

Чтобы избежать trunaction, используйте буфер размером 64 КБ. Пакеты UDP не могут быть больше этого (16-битное поле в протоколе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...