C ++ UDP Receving - PullRequest
       25

C ++ UDP Receving

0 голосов
/ 23 марта 2020

У меня есть проблема, которую я пытался сгладить весь день. Ситуация выглядит следующим образом:

  1. У меня есть список серверов - скажем, 10 разных серверов.
  2. Я хочу отправить широковещательное сообщение Предложения с помощью команды sendto на все 10 серверов.
  3. Затем я хочу прослушать и подождать, пока 10 серверов ответят ACK + какое-нибудь сообщение.
  4. Через некоторое время тайм-аут с использованием данных от ответивших серверов. (время будет изменяться в зависимости от количества запросов)

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

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

Я также мог бы сначала настроить поток прослушивания, а затем запустить sendto в отдельном потоке, но затем слушатель (который является целой программой) находится в другом потоке вне main.

Итак, мой вопрос состоит из двух частей: какой из этих подходов (если таковой имеется) кажется наиболее подходящим с учетом того, что я пытаюсь сделать? Во-вторых, есть ли очередь на сокете. Как скажем, это не 10, а 1000 серверов - если сообщение приходит, пока оно не готово к приему, будет ли это сообщение отброшено?

Я открыт для предложений о других способах реализации.

Заранее спасибо!

1 Ответ

2 голосов
/ 23 марта 2020

Большинство персональных компьютеров в наши дни расположены за брандмауэрами, которые блокируют любые входящие UDP-пакеты - на самом деле, большинство персональных компьютеров в наши дни также находятся за уровнем трансляции NAT и даже не имеют своего собственного Inte rnet -routable. Айпи адрес. Я бы побеспокоился об этом, прежде чем беспокоиться об отсутствии случайного входящего UDP-сообщения из-за проблем с синхронизацией.

Тем не менее, в случае, если ваш клиент работает с открытым Inte rnet (или за брандмауэром, который настроен на пропуск пакетов UDP), проблема синхронизации на самом деле не является проблемой, поскольку сетевой стек выделяет буфер входящих данных для каждого сокета как часть вызова socket(). После успешного вызова bind() для сокета все UDP-пакеты, поступающие на порт этого сокета, будут помещены в буфер входящих данных сокета и готовы к передаче вашему коду при следующем вызове recvfrom(). Важно отметить, что эта буферизация будет происходить независимо от того, находится ли ваш поток внутри вызова recvfrom() или нет.

Возможно заполнение входящего буфера данных (он имеет конечный размер, обычно около 64 КБ) ); в этот момент любые дополнительные входящие пакеты UDP будут отброшены. Обычный способ избежать этого - убедиться, что вы вызываете recvfrom() как можно скорее, или, если этого недостаточно, вы можете использовать setsockopt(), чтобы указать сетевому стеку увеличить размер входящего буфера данных сокета.

Между тем, ваши вызовы sendto(), скорее всего, завершатся sh быстро, поскольку sendto() возвращается, как только данные в вашем массиве копируются в буфер исходящих данных сокета. В частности, sendto() не ожидает байтов до go по сети или (обычно) даже байтов до вашей сетевой карты. В худшем случае он может блокироваться, пока в буфере исходящих данных не будет достаточно места для размещения данных; и буфер исходящих данных всегда истощается со скоростью линии вашего сетевого устройства.

...