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

У меня есть проблема в понимании того, что вызовов recv()/вызов recvfrom() возвращение с не blockig UDP сокет.

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

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

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

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

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

Edit:

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

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

3 ответов


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

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

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

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

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

(Stevens, TCP / IP Illustrated, Volume 1, p. 160)


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

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


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

Edit: я уверен, что вы не можете получить половину датаграмму. Либо дейтаграмма прибыла в буфер ввода, либо нет.