UDP recv / recv от нескольких отправителей - PullRequest
3 голосов
/ 05 января 2012

Good Day,

Я занимаюсь разработкой приложения на VC ++, которое взаимодействует по протоколу UDP с winsock в Windows XP.Ранее я был в состоянии предположить, что все пакеты, полученные инструментом, были от единственной цели.Однако сейчас я делаю трансляцию.Поток прослушивания имеет минимальные издержки и должен тратить все свое время на строку ниже:

rv = recvfrom(socket, 
              p_buffer_p, 
              p_size,
              0,
              (sockaddr*)&clientService_in, //This is set to do a broadcast recv
              &SenderAddrSize);

Мой вопрос заключается в том, могу ли я предположить, что буфер, который я получаю из одного возврата из recvfrom,единственная цель.То есть 1 вызов для отправки в отправляющем приложении равен 1 возврату из recvfrom в принимающем приложении?Или несколько отправок от нескольких отправителей могут быть объединены в 1?

Я предполагаю, что одна отправка от цели не может быть разделена на несколько возвратов из recvfrom.Я всегда предполагал это и никогда не сталкивался с проблемой.

Еще одна вещь, это сокет типа SOCK_DGRAM.

Ответы [ 2 ]

6 голосов
/ 05 января 2012

Нет, UDP-сообщение не может быть разделено.Они прибывают, как они были отправлены.Кроме того, несколько сообщений UDP НЕ объединяются.

Таким образом, N sendto сообщений соответствуют N recvfrom от вызовов.

Цитата из wiki :

Дейтаграммы - пакеты отправляются индивидуально и проверяются на целостность только в случае их поступления.Пакеты имеют определенные границы, которые учитываются при получении, что означает, что операция чтения в сокете-получателе приведет к получению всего сообщения в том виде, в котором оно было первоначально отправлено.

2 голосов
/ 10 января 2012

Вы правы, что один вызов recvfrom () вернет не более одну UDP-дейтаграмму.Но нет никакой гарантии, что каждая дейтаграмма действительно прибудет.

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

Все может стать очень сложным, потому что невозможно заранее точно определить, насколько большой размер слишком велик.Существуют различные алгоритмы обнаружения, но все они равны пробам и ошибкам.Хуже того, брандмауэры, маршрутизаторы и операционные системы могут (и часто делают) со временем менять свое поведение на фрагментированные дейтаграммы.Могут быть сценарии, когда пакет определенного размера или состава всегда будет отброшен, потому что он нарушает какое-то правило брандмауэра.

Поэтому никогда не предполагайте, что sendto () обязательно приведет к recvfrom (), и попытайтесьоставляйте ваши дейтаграммы маленькими (менее 1400 байт достаточно безопасно, менее 512 байт очень безопасно).

...