Неблокирующий ввод-вывод UDP против блокирующего ввода-вывода UDP в Java

Неблокирующие TCP/IP SocketChannel и Selector в NIO помогают мне обрабатывать множество соединений TCP/IP с небольшим количеством потоков. А как насчет UDP DatagramChannels? (Должен признаться, что я не очень хорошо знаком с UDP.)

Операции отправки UDP не блокируются, даже если DatagramChannel не работает в режиме блокировки. Есть ли действительно случай, когда DatagramSocket.send(DatagramPacket) блокируется из-за перегрузки или чего-то подобного? Мне действительно любопытно, есть ли такой случай и какие возможные случаи существуют в производственной среде.

Если DatagramSocket.send(DatagramPacket) на самом деле не блокируется, и я не собираюсь использовать подключенный DatagramSocket и привязываться только к одному порту, есть ли преимущества в использовании неблокирующего режима с DatagramChannel и Selector?


person trustin    schedule 20.02.2009    source источник


Ответы (3)


Прошло некоторое время с тех пор, как я использовал Java DatagramSockets, Channels и тому подобное, но я все еще могу вам помочь.

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

person James    schedule 20.02.2009
comment
Что произойдет, если буфер ядра будет заполнен слишком быстрой записью в сокет UDP? - person trustin; 20.02.2009
comment
Ваша запись (на уровне пользователя) будет заблокирована до тех пор, пока ядро ​​​​не очистит буфер отправки сокетов. - person JLR; 20.02.2009
comment
Таким образом, существует очевидная разница между блокирующими и неблокирующими сокетами UDP, точно так же, как разница между блокирующими и неблокирующими сокетами TCP. Я написал простой PoC-клиент и убедился, что send() неблокирующего канала UDP часто возвращает 0, а блокирующий никогда не возвращает 0. Спасибо! - person trustin; 20.02.2009

UDP не блокируется (он блокируется только во время передачи данных в ОС). Это означает, что если в какой-то момент следующий переход/коммутатор/компьютер не может буферизовать пакет UDP, он его отбрасывает. Это может быть желательным поведением в некоторых ситуациях. Но это то, о чем вам нужно знать.

UDP также не гарантирует

  • пакеты доставки в порядке их отправки.
  • не разбивать большие пакеты.
  • пересылать пакеты через коммутаторы. Часто пересылка UDP между коммутаторами отключена.

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

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

person Peter Lawrey    schedule 20.02.2009

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

person Andras Balázs Lajtha    schedule 10.04.2013