UDP сервера и привязка порта - PullRequest
1 голос
/ 04 января 2012

Я пишу эту игру на Java и у меня проблемы с сетевой архитектурой.

Я решил, что буду использовать UDP-пакеты. Я только в начале, но проблема, с которой я сталкиваюсь, заключается в том, что, похоже, сервер должен отвечать точно с того же IP / порта на клиент (который находится за маршрутизатором, который использует NAT), когда клиент подключил этот сервер.

Например, у меня есть клиент A за маршрутизатором. Клиент A имеет локальный IP-адрес 192.168.8.100 и подключается к серверу B через порт 1234. Сервер подключен к 11.11.11.11:2345.

Когда клиент A подключается к серверу B, он использует 192.168.8.100:1234, но маршрутизатор преобразует это в (например) 22.22.22.22:6789.

Теперь, когда сервер хочет отправить пакеты этому клиенту, это должно быть с 11.11.11.11:2345. Я хотел бы отправить данные из другого порта, например 11.11.11.11:2222, но, похоже, это не работает, по крайней мере, с моим маршрутизатором.

Я хочу использовать другой порт, потому что я хочу иметь два потока, один для прослушивания и один для отправки данных, и каждый поток будет иметь свой собственный DatagramSocket. Но, как я сказал, когда клиент А подключается к серверу через порт 2345, я не могу отправлять данные с порта 2222.

Кто-нибудь знает, как это обрабатывается? Я делаю это на Java, но это не проблема конкретного языка.

UPDATE

После того как @Perception прокомментировал, у меня есть еще несколько вопросов относительно его комментариев:

ОК, поэтому, если я правильно понимаю, если у меня есть сервер, на котором размещено 1000 игр, в каждой из которых по 2 игрока, вся отправка / получение должна осуществляться через один DatagramSocket.

Насколько я понимаю, DatagramSocket является потокобезопасным, поэтому, я думаю, у меня может быть один поток, выполняющий:

datagramSocket.receive();

в то время как второй поток выполняет

datagramSocket.send(.....);

Правильно?

Кроме того, два потока могут отправлять данные одновременно через один и тот же DatagramSocket? Является ли отправка каким-либо образом сериализованным, что означает, что вторая send () запускается только после завершения предыдущего send () или данные отправляются одновременно?

Ответы [ 2 ]

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

Это одно из самых хитрых различий между TCP и UDP.

Когда инициируется новый сеанс TCP, серверный вызов метода accept () дает вам новый сокет, а ОС обрабатывает мультиплексирование различных сеансов.для тебя.С UDP вы должны справиться с мультиплексированием самостоятельно.Но вам нужно сделать это так, чтобы это работало с NAT и другими брандмауэрами.

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

Это дает вам два варианта:

  1. Вы можете выполнять все свои коммуникации черезодин порт.Это не плохой вариант, это просто означает, что вам нужен способ идентифицировать клиентские сеансы и направить их в соответствующий поток.

  2. Вы можете создать отдельный порт и дать клиенту команду:вместо этого пошлите к этому.Пусть сервер прослушивает фиксированный порт.Клиент отправляет туда сообщение, затем сервер устанавливает новый сеансовый порт и отправляет этот номер обратно клиенту, используя порт прослушивания сервера.Затем клиент отправляет сообщение на порт сеанса, что заставляет NAT открыть этот порт и разрешить возврат трафика.Теперь клиентский и серверный потоки имеют свою собственную пару частных портов.

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

0 голосов
/ 06 января 2012

gorann, я не уверен, правильно ли я вас понимаю, но похоже, что вы пытаетесь контролировать порт, на котором сервер взаимодействует с клиентом.Нет никакого способа контролировать это, и по уважительным причинам.

...