Вопрос

У меня простая настройка клиент/сервер.Сервер находится на C, а клиент, который запрашивает сервер, — на Java.

Моя проблема в том, что когда я отправляю по соединению данные с интенсивным использованием полосы пропускания, например видеокадры, до половины пакетов теряется.Я проверяю правильность фрагментации пакетов udp на стороне сервера (максимальная длина полезной нагрузки udp составляет 2^16).Я проверил, что сервер отправляет пакеты (распечатайте результат sendto()).Но Java, похоже, не получает и половины данных.

Более того, когда я переключаюсь на TCP, все видеокадры проходят, но задержка начинает увеличиваться, добавляя задержку в несколько секунд после нескольких секунд выполнения.

Есть ли что-то очевидное, чего мне не хватает?Я просто не могу этого понять.

Это было полезно?

Решение

Получите сетевой инструмент, как Вирешарк Итак, вы можете увидеть, что происходит на проводе.

UDP не предпринимает никаких попыток повторной передачи, поэтому, если пакет куда -то сброшен, программа зависит от потери. TCP будет усердно работать, чтобы доставить все пакеты в программу по порядку, отбрасывая DUPS и запрашивая потерянные пакеты самостоятельно. Если вы видите высокую задержку, я бы поспорил, что вы также увидите много потерь пакетов с TCP, которые будут отображаться в качестве ретрансмиссии с сервера. Если вы не видите ретрансмиссии TCP, возможно, клиент не обрабатывает данные достаточно быстро, чтобы не отставать.

Другие советы

Любой прикладной протокол на основе UDP неизбежно будет подвержен потере пакетов, их переупорядочению и (в некоторых случаях) дублированию.Буква «U» в UDP может означать «ненадежный», как в «ненадежном протоколе дейтаграмм».(ОК, на самом деле это означает «Пользователь»…но это, безусловно, хороший способ запомнить характеристики UDP.)

Потери пакетов UDP обычно происходят из-за того, что ваш трафик превышает емкость буфера одного или нескольких «переходов» между сервером и клиентом.Когда это происходит, пакеты отбрасываются...и поскольку вы используете UDP, уведомление на уровне транспортного протокола о том, что это происходит, отсутствует.

Если вы используете UDP в приложении, приложение должно учитывать ненадежную природу UDP, реализуя свои собственные механизмы для обработки отброшенных и неупорядоченных пакетов, а также для собственного управления потоком.(Приложение, которое рассылает UDP-пакеты, не задумываясь о том, какой эффект это может оказать на уже перегруженную сеть, является гражданин плохой сети.)

(В случае TCP пакеты, вероятно, также отбрасываются, но TCP обнаруживает и повторно отправляет отброшенные пакеты, а механизм управления потоком TCP срабатывает, чтобы замедлить скорость передачи данных.Конечным результатом является «задержка».)

РЕДАКТИРОВАТЬ - Судя по комментарию ОП, причина его проблемы заключалась в том, что клиент не «слушал» какое-то время, в результате чего пакеты (предположительно) отбрасывались ОС клиента.Способ решения этой проблемы заключается в следующем:

  1. используйте выделенный поток Java, который только читает пакеты и ставит их в очередь на обработку, и

  2. увеличьте размер очереди пакетов ядра для сокета.

Но даже если вы примете эти меры, пакеты все равно могут быть отброшены.Например, если машина перегружена, приложение может не получать интервалы времени выполнения достаточно часто, чтобы читать и ставить в очередь все пакеты, прежде чем ядру придется их отбросить.

РЕДАКТИРОВАТЬ 2 - Ведутся споры о том, подвержен ли UDP дубликату.Это, безусловно, правда, что UDP не имеет встроенного обнаружения или предотвращения дублирования.Но верно также и то, что структура маршрутизации IP-пакетов, которой является Интернет, вряд ли будет самопроизвольно дублировать пакеты.Таким образом, дубликаты, если они и происходят, скорее всего, возникнут из-за того, что отправитель решил повторно отправить пакет UDP.Таким образом, на мой взгляд, хотя UDP и подвержен проблемам с дубликатами, он не вызывает их. как таковой ...если нет ошибки в стеке протоколов ОС или в структуре IP.

Хотя UDP поддерживает пакеты длиной до 65535 байтов (включая Заголовок UDP, который составляет 8 байтов - но см. Примечание 1), основной транспорт между вами и пунктом назначения не поддерживают IP -пакеты так долго. Например, рамки Ethernet имеют максимальный размер 1500 байтов - с учетом накладных расходов для заголовков IP и UDP, что означает, что любой пакет UDP с длиной полезной нагрузки данных более чем около 1450, вероятно, будет фрагментирован на несколько данных IP.

Пакет UDP максимального размера будет фрагментирован как минимум на 45 отдельных Datagrams - и, если таковые имеются один Из этих фрагментов потерян, весь пакет UDP потерян. Если ваш базовый уровень потери пакетов составляет 1%, ваша приложение увидит убыток около 36%!

Если вы хотите видеть потерянное меньше пакетов, не отправляйте огромные пакеты - ограничьте свои данные в каждом пакете примерно 1400 байтами (или даже выполняйте свой собственный «Path MTU Discovery», чтобы выяснить максимальный размер, который вы можете безопасно отправить без фрагментации) Анкет


  1. Конечно, UDP также подлежит ограничениям IP, а Datagrams IP имеет максимальный размер 65535, включая заголовок IP. Заголовок IP варьируется в размере от 20 до 60 байт, поэтому максимальное количество данных, переносимых в пакете UDP, может составлять всего 65467.

Проблема может заключаться в том, что ваш буфер передачи заполняется в вашем UDPSocket. Отправить только сумму байтов за один ход, указанный UDPSocket.getSendBufferSize(). Анкет Использовать setSendBufferSize(int size) Чтобы увеличить это значение.

Если #send () используется для отправки DataGrampacket, который больше, чем настройка SO_SNDBUF, то он является специфичным для реализации, если пакет отправлен или отброшен.

IP поддержка пакеты до 65535 байтов, включая 20 Byte IP -пакет заголовок. UDP поддержка DataGRAMS до 65507 байтов, плюс заголовок IP 20 байтов и 8 Byte UDP заголовок. Однако сеть MTU является практическим пределом, и не забывайте, что это включает не только эти 28 байтов, но и заголовок кадров Ethernet. А настоящий Практическое ограничение для нефрагментированного UDP - это минимальный MTU на 576 байт меньше всех накладных расходов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top