Как UDP отправлять и получать по одному и тому же порту? - PullRequest
9 голосов
/ 29 октября 2009

Мне нужно иметь возможность отправлять и получать пакеты UDP по одному и тому же порту. Я могу прослушивать, скажем, порт 5000, но моя отправка использует случайный высокий порт. Система, с которой я работаю, написанная на VB, делает это, и мне нужно написать ответчик UDP для отладки различных проблем протокола.

Я использую библиотеку сокетов с открытым исходным кодом C ++ из http://www.alhem.net (Андерс Хедстрем) и смог использовать UdpSocket :: Bind () для получения входящих пакетов UDP с помощью виртуальной функции UdpSocket :: OnRawData ( ), но не удалось заставить UdpSocket :: Open () (вызывает соединение) заставить UdpSocket :: Send () использовать порт, выбранный в Bind () (вместо этого используется случайный порт с большим числом).

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

У кого-нибудь есть идеи по поводу того, что мне следует попробовать?
--thanks -

Ответы [ 2 ]

9 голосов
/ 29 октября 2009

Система состоит из нескольких узлов прослушивание на одном и том же порту (разные ip адр 'ы). Система [A] отправляет дейтаграмму Система [B]. Система [B] асинхронно отвечает и отправляет датаграммы [A] все используют один и тот же порт. Даже если [B] идентифицирует порт [A], [A] нет прослушивание этого порта

Я не уверен, что понимаю фразу «все используют один и тот же порт» в этом предложении. Если A отправляет дейтаграмму B, B сразу узнает IP-адрес и порт A (быстрая проверка документации вашей библиотеки показывает, что OnRawData имеет параметр struct sockaddr *sa, если вы приведете его к sockaddr_in*, вы сможете извлечь IP: пара портов). Вы можете использовать этот IP: порт для отправки дейтаграмм, и А получит их. A не «прослушивает» этот порт в том смысле, что он не вызвал listen () для сокета, но поскольку A владеет сокетом, который привязан к этому порту (явно ли он вызван bind () или назначен случайный порт с помощью ОС) он получит данные.

Теперь, если вы хотите, чтобы ВСЕ ваше соединение между узлами проходило через ваш фиксированный порт, вы можете сделать это. Вам просто нужно отправить все свои дейтаграммы через сокет «прослушивания». Если каждый узел «слушает» один и тот же порт, это означает, что каждый узел имеет сокет, связанный с этим портом. Если вы хотите, чтобы дейтаграммы, отправленные из А в В, появлялись с этого фиксированного порта, вы должны отправить их через этот сокет. Я предполагаю, что именно поэтому bind () не работает для вашего отправляющего сокета - A имеет сокет, привязанный к порту X, затем вы создаете другой сокет и пытаетесь привязать его к тому же порту X, bind () завершается неудачно, так как порт уже занят (и вы не проверяете наличие ошибок :), а затем ОС назначает случайный свободный порт выше 1024.

Примечание 1: я везде использую «прослушивание» в кавычках, потому что концепция не очень ясна в контексте сокетов UDP. После того как вы создали сокет и связали его с портом, явно вызвав bind () или отправив данные и позволив ОС привязать его к порту, вы можете получать данные отовсюду через него. Не требуется вызовов listen () или accept ().

Примечание 2: Вы говорите, что UdpSocket :: Open () вызывает метод connect (), но это не имеет особого смысла - connect () делает очень мало для UDP-сокетов - он просто устанавливает адрес по умолчанию, поэтому вы можете использовать send () вместо sendto () и не указывать адрес при каждой отправке.

Надежда, которая проясняет ситуацию. <Ч /> Изменить, чтобы ответить на комментарий OP: я никогда не использовал эту библиотеку, но согласно их документации UdpSocket существует 4 перегрузки метода Bind (), и каждый из них каким-то образом принимает порт. Никто из них не работает для вас?

4 голосов
/ 29 октября 2009

Двунаправленная линия связи всегда включает двух участников: на стороне сервера и на стороне клиента.

Клиент ожидает соединения с сервером через определенный порт: поэтому на стороне сервера необходимо привязать () к сокету.

На стороне клиента необходимо открыть сокет для сервера: на самом деле не имеет значения, какой сокет выбран (за исключением необходимости его освобождения).

Другими словами, не пытайтесь указать сокет на стороне клиента: стек сетевых протоколов назначит его вашему клиенту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...