программирование неблокирующих сокетов udp на C:Что я могу получить?

StackOverflow https://stackoverflow.com/questions/2239986

Вопрос

У меня проблема с пониманием того, что return()/recvfrom() возвращает из неблокируемого UDP-сокета.

Немного более конкретно и по сравнению с TCP (поправьте меня, если я ошибаюсь):

  • Блокирующий сокет (TCP или UDP) не вернется из Recv(), пока в буфере не появятся какие-либо данные.Это может быть некоторое количество байтов (TCP) или полная датаграмма (UDP).

  • Неблокирующий TCP-сокет возвращает либо EWOULDBLOCK (linux)/WSAEWOULDBLOCK (windows), либо байты, которые в данный момент находятся в буфере.Поскольку данные TCP представляют собой поток, не имеет значения, сколько байтов возвращается.

Теперь вопрос:

  • Неблокирующий сокет UDP также возвращает WOULDBLOCK (linux)/WSAEWOULDBLOCK (windows), если доступные данные отсутствуют.Но если данные доступны, возвращает ли неблокирующий сокет UDP только несколько байтов, что может означать, что вы получаете только половину дейтаграммы, ИЛИ сокет UDP всегда возвращает полные дейтаграммы?

Редактировать:

Под «половиной датаграммы» я подразумеваю следующее:что произойдет, если я вызову Recv() как раз в тот момент, когда сокет в данный момент получает дейтаграмму.В этот момент в буфере есть несколько байтов, но датаграмма еще не завершена.

Ваши объяснения и комментарии приветствуются.Спасибо!

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

Решение

Наконец-то появился повод выкопать книги Стивенса из старых офисных коробок.

При условии, что буфер достаточно велик, стандартные сокеты Беркли recv() и recvfrom() функции никогда не возвращают частичную датаграмму.Дейтаграмма недоступна приложению до тех пор, пока ядро ​​полностью не получит и не соберет ее заново.

Интересно, что сегодня это не является большой (никакой?) проблемой, другие интерфейсы сетевого программирования не согласны с поведением, когда предоставленный буфер слишком мал:

Традиционная версия API сокетов Беркли усекает датаграмму, отбрасывая все лишние данные.Будет ли приложение уведомлено, зависит от версии.(4.3BSD Reno и более поздние версии могут уведомить приложение о том, что датаграмма была усечена.)

API сокетов в SVR4 (включая Solaris 2.x) не усекает датаграмму.Любые лишние данные возвращаются при последующих чтениях.Приложение не уведомляется о том, что из одной дейтаграммы UDP выполняется несколько операций чтения.

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

(Стивенс, TCP/IP Illustrated, том 1, стр.160)

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

Да, UDP просто возвращает данные, переданные в этой датаграмме.UDP не ориентирован на потоки, как TCP.Дейтаграммы представляют собой дискретную передачу и на самом деле никак не связаны с другими дейтаграммами.По этой причине параметр сокета для TCP — SOCK_STREAM.

Положительная сторона этого заключается в том, что вы можете почувствовать отдельные передачи, что не так-то просто сделать с TCP.

Я считаю, что вы получите ровно одну или ноль датаграмм.Но я не могу это подтвердить в данный момент.Возможно, кто-то другой может дать хорошую ссылку?

Редактировать:Я почти уверен, что вы не сможете получить половину датаграммы.Либо дейтаграмма прибыла во входной буфер, либо нет.

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