connect()
в UDP не обеспечивает демультиплексирование соединения.
connect()
делает две вещи:
Устанавливает адрес по умолчанию для функций передачи, которые не принимают адрес назначения (send()
, write()
и т. Д.)
Устанавливает фильтр для входящих дейтаграмм.
Важно отметить, что входящий фильтр просто отбрасывает датаграммы, которые не совпадают. Он не передает их в другом месте. Если к одному и тому же адресу привязано несколько сокетов UDP, некоторые ОС выберут один (может быть, случайный, может быть, последний созданный) для каждой дейтаграммы (демультиплексирование полностью нарушено), а некоторые доставят все дейтаграммы всем (демультиплексирование завершится успешно, но невероятно неэффективен). Оба из них "неправильные вещи". Даже ОС, которая позволяет выбирать между двумя вариантами поведения с помощью опции сокета, по-прежнему работает не так, как вы хотели. Время между bind()
и connect()
- это лишь малая часть этой загадки нежелательного поведения.
Для обработки UDP с несколькими одноранговыми узлами использовать один сокет в режиме без установления соединения . Чтобы несколько потоков обрабатывали полученные пакеты параллельно, вы можете либо
- вызов
recvfrom
в нескольких потоках, которые обрабатывают данные (это работает, потому что сокеты дейтаграмм сохраняют границы сообщений, вы никогда не сделаете это с потоковым сокетом, таким как TCP), или
- вызов
recvfrom
в одном потоке, который не выполняет никакой обработки, просто помещает сообщение в очередь для потока, ответственного за его обработку.
Даже если у вас была ОС, которая давала вам возможность отправлять входящий UDP на основе назначенных адресов одноранговых узлов (эмуляция соединения), выполнение этой операции внутри ОС все равно не будет более эффективным, чем в серверном приложении. и диспетчер пользовательского пространства, настроенный на ваши шаблоны трафика, вероятно, будет работать значительно лучше, чем диспетчер с универсальным размером для всех, предоставляемый ОС.
Например, сервер DNS (DHCP) будет осуществлять транзакции с большим количеством разных хостов, почти все из которых будут работать через порт 53 (67-68) на удаленном конце. Таким образом, хеширование на основе удаленного порта будет бесполезным, вам нужно хешировать на хосте. И наоборот, сервер кэширования, поддерживающий кластер серверов веб-приложений, будет работать с несколькими узлами и большим количеством различных портов. Здесь будет лучше хеширование на удаленном порту.
Выполните связывание соединений самостоятельно, не используйте эмуляцию сокетного соединения.