Intereting Posts
Хорошее программирование имеет много одноэлементных classов в проекте? Должен ли я использовать cstdint? Что означает термин «пустой цикл» точно в C и C ++? Как сортировать строки по алфавиту? Каковы реальные C ++ языковые конструкции, поддерживаемые кодом устройства CUDA? Проверка строки в пределах короткого диапазона Можно ли связать простой файл с исполняемым файлом? Может ли какая-либо функция быть удаленной функцией? Неупорядоченный набор пар, ошибка компиляции Netbeans 8.0.2 возвращает «Во время запуска программы с кодом 0xc0000135» Переместить элемент списка в конец в STL C ++ Неразрешенный внешний символ с шаблонами classов как я могу читать ровно 128 байт из streamа в строковый объект? Как получить все аргументы из следующей функции в c / c ++? Почему я получаю плохую производительность с SDL2 и SDL_RenderCopy внутри двойного цикла для всех пикселей?

Разделяют ли UDP-сокеты полученные данные в отдельных сообщениях или читают ли они как можно больше данных одновременно?

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

Во-первых, в приложении-отправителе я отправляю некоторые данные двумя отдельными вызовами. Сначала я отправляю эти 15 байт:

[MYHEADER]hello

… затем, сразу после этого, я посылаю еще 15 байт:

[MYHEADER]world

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

Вот какой-то псевдокод, который показывает, как я обрабатываю сокет для входящих данных в каждом кадре:

 uint32 PendingSize; while (Socket->HasPendingData(PendingSize)) { uint32 BytesRead; uint8 MessageData[kMaxMessageSize]; if (Socket->Recv(MessageData, kMaxMessageSize, BytesRead)) { // Do stuff here // Will BytesRead be equal to PendingSize? } } 

HasPendingData завершает вызов ioctlsocket с помощью FIONREAD , возвращая, ожидают ли данные в буфере приема и PendingSize количеством ожидающих байтов. Recv вызывает recv для чтения этих данных в буфер, который я могу прочитать. Если он возвращает true, я отвечаю на полученные данные.

Вот мой вопрос. Какой из этих сценариев точно отражает то, что произойдет в этой ситуации?

Вариант A.

  1. HasPendingData возвращает true и показывает ожидающий размер 15 байт. Recv дает мне сообщение [MYHEADER]hello .
  2. HasPendingData возвращает true и показывает ожидающий размер 15 байт. Recv дает мне сообщение [MYHEADER]world .
  3. HasPendingData возвращает false.

Вариант B.

  1. HasPendingData возвращает true и показывает ожидающий размер 30 байт. Recv дает мне сообщение [MYHEADER]hello[MYHEADER]world .
  2. HasPendingData возвращает false.

Любое понимание очень ценится. Спасибо!

UDP-дейтаграммы являются индивидуальными и автономными.

send() и sendto() отправлять новую датаграмму каждый раз.

recv() и recvfrom() читают одну целую дейтаграмму. Если ваш буфер слишком мал для получения данной дейтаграммы, вы получите сообщение WSAEMSGSIZE ошибке WSAEMSGSIZE и что датаграмма будет потеряна, если вы не укажете флаг MSG_PEEK .

FIONREAD сообщает вам общее количество необработанных байтов в буфере приема сокета, а не количество дейтаграмм или размер этих датаграмм. Это четко указано в документации :

FIONREAD
Используется для определения количества данных, ожидающих входного буфера сети, которые можно прочитать из сокетов s. Параметр argp указывает на длинное значение без знака, в котором ioctlsocket сохраняет результат. FIONREAD возвращает количество данных, которое может быть прочитано в одном вызове функции recv, что может быть не таким, как общий объем данных, поставленных в очередь в сокете. Если s ориентирован на сообщения (например, введите SOCK_DGRAM), FIONREAD по-прежнему возвращает количество ожидающих данных в сетевом буфере, однако количество, которое действительно может быть прочитано в одном вызове функции recv, ограничено размером данных, записанным в вызове функции send или sendto.

Если вам нужно проверить размер следующей дейтаграммы, вызовите recv() или recvfrom() с флагом MSG_PEEK . Как только вы определили фактический размер дейтаграммы, вы можете прочитать его без флага, чтобы он удалялся из буфера сокета. В противном случае просто выделите буфер, который достаточно велик, чтобы разместить самую большую датаграмму, которую вы когда-либо получили, или даже просто 65535, который является самым большим размером, поддерживаемым UDP.

Итак, чтобы ответить на ваш вопрос, что действительно произойдет в вашем примере, это вариант A , за исключением того, что первая HasPendingData сообщит 30 ожидающих байтов вместо 15.