Максимальный размер буфера отправки/возврата Java DatagramPacket (UDP)
В Java при использовании DatagramPacket
предположим, что у вас есть буфер byte[1024*1024]
. Если вы просто передадите это для DatagramPacket, когда отправка/получение будет принимать Java-запрос для блока DatagramPacket до тех пор, пока он не прочитает весь мегабайт?
Я спрашиваю, будет ли Java разбивать его или просто попытаться отправить всю вещь, которая будет удалена.
Обычно ограничение размера составляет около 64 КБ для UDP-пакета, но я задавался вопросом, так как Java API допускает массивы байтов, если это предел, и что-то супер огромное, отбрасывается или распадается и повторно собрано для вас.
Если он отбрасывается, какой вызов API скажет мне максимальную полезную нагрузку данных, которую я могу использовать в вызове Java? Я слышал, что IPv6 также имеет jumbo frames, но DatagramPacket (или DatagramSocket
) поддерживает это, поскольку UDP определяет спецификацию заголовка?
Ответы
Ответ 1
DatagramPacket
- это всего лишь оболочка сокета на основе UDP, поэтому применяются обычные правила UDP.
64 килобайта - это теоретический максимальный размер полной IP-дейтаграммы, но гарантировано, что будет маршрутизировано только 576 байтов. На любом заданном сетевом пути ссылка с наименьшим максимальным передающим модулем определит фактический предел. (1500 байт, меньше заголовков - общий максимум, но невозможно предсказать, сколько заголовков там будет настолько безопасным для ограничения сообщений примерно на 1400 байт.)
Если вы переходите через ограничение MTU, IPv4 автоматически разбивает дейтаграмму на фрагменты и собирает их в конце, но только до 64 килобайт и только если все фрагменты пройдут. Если какой-либо фрагмент потерян или если какое-либо устройство решает, что оно не похоже на фрагменты, то весь пакет будет потерян.
Как отмечалось выше, невозможно заранее знать, каким будет MTU пути. Существуют различные алгоритмы для экспериментирования, но многие устройства неправильно реализуют (или намеренно игнорируют) необходимые стандарты, поэтому все сводится к проб и ошибок. Или вы можете просто догадаться о 1400 байт за сообщение.
Что касается ошибок, если вы пытаетесь отправить больше байтов, чем разрешено ОС, вы должны получить ошибку EMSGSIZE
или ее эквивалент. Если вы отправляете меньше этого, но больше, чем позволяет сеть, пакет просто исчезнет.
Ответ 2
@Михай Данила. Поскольку я не мог добавить комментарий к вышеуказанному ответу, то зачем писать в раздел ответа.
В продолжение вашего ответа на размер MTU в моей практике я пытаюсь использовать NetworkInterface.getMTU()-40
для установки размера буфера DatagramSocket.setSendBufferSize()
. Поэтому, стараясь не полагаться на getSendBufferSize()
, нужно убедиться, что он соответствует разным размерам окон на разных платформах и является общепринятым в ethernet (игнорируя дозвон на минуту). Я не закодировал его до 1460 байт (1500-20-20), потому что в окнах размер MTU имеет универсальный 1500. Однако размер окна окна платформы составляет 8192 байта, но я считаю, установив SO_SNDBUF в < MTU, я обременяю сетевой/IP-уровень меньше, и для всех переходов для маршрутизаторов и получателей некоторые накладные расходы. Таким образом, сокращение некоторой задержки по сети.
Аналогично, для буфера приема я использую максимум 64 Кбайт или 65535 байт. Таким образом, моя программа переносится на разных платформах, используя разные размеры окон.
Как вы думаете, это звучит нормально? Я не применял никаких инструментов для измерения каких-либо различий, но предполагал, что это дело основано на том, что там.