Я кое-что прочитал об обходе UDP NAT, и я достаточно уверен, что понимаю основы, но я все еще борюсь с реализацией.
В моем проекте есть глобально доступный сервер и клиенты за nat. Это игра, в которой базовый запрос join_game отправляется от клиента к серверу, а затем сервер отправляет обновления каждый интервал. Я тестировал дома и забыл, что у меня включен DMZ на моем маршрутизаторе, поэтому он работал нормально. Я отправил это некоторым друзьям для проверки, и они не могут получать обновления с сервера.
Вот текущая методология, все пакеты UDP:
- Клиент открывает сокет и отправляет запрос на присоединение к серверу.
- Сервер получает запрос и ответный адрес сообщения и отвечает клиенту: да, вы можете присоединиться, и, кстати, я буду отправлять обновления на ваш ответный ip/порт, который выглядит так.
- Клиент перехватывает ответ, затем закрывает сокет и запускает класс потокового прослушивателя UDP для прослушивания порта ответа, о котором нам сообщил сервер.
- Затем клиент перехватывает обновления сервера, которые переполняются, и обрабатывает их по мере необходимости. Время от времени клиент открывает новый сокет и отправляет UDP-пакет с обновлением на сервер (какие клавиши нажаты и т. д.).
Насколько я понимаю, ответный адрес, который получает сервер, должен иметь правильный порт для прохождения клиентского nat. И отправка пакетов туда достаточно часто будет поддерживать действие правила обхода nat.
Этого не происходит. Клиент отправляет запрос на присоединение и получает ответ сервера на этом сокете. Но когда я закрываю сокет, а затем запускаю потоковый прослушиватель UDP на порту ответа, он ничего не улавливает. Это почти как если бы правило обхода действительно только для одного пакета ответа.
Я могу включить код, если это необходимо, но, честно говоря, это несколько слоев классов и объектов, и он делает то, что я описал выше. Код работает, когда я включаю DMZ, но не когда он выключен.
Я включу некоторые фрагменты, представляющие интерес.
Вот серверный обработчик запроса на присоединение. client_address передается из потокового обработчика и является атрибутом SocketServer.BaseRequestHandler, self.client_address. Без разбора, просто передано.
def handle_player_join(self, message, reply_message, client_address):
# Create player id
player_id = create_id()
# Add player to the connected nodes dict
self.modules.connected_nodes[player_id] = client_address
# Create player ship entity
self.modules.players[player_id] = self.modules.factory.player_ship( position = (320, 220),
bearing = 0,
)
# Set reply to ACK, and include the player id and listen port
reply_message.body = Message.ACK
reply_message.data['PLAYER_ID'] = player_id
reply_message.data['LISTEN_PORT'] = client_address[1]
print "Player Joined :"+str(client_address)+", ID: "+str(player_id)
# Return reply message
return reply_message
Друг упомянул, что, возможно, когда я отправляю запрос на присоединение, а затем получаю ответ, я не должен закрывать сокет. Держите этот сокет живым и сделайте его слушателем. Я не уверен, что закрытие сокета как-то повлияет на обход nat, и я не знаю, как создать потоковый прослушиватель udp, который берет уже существующий сокет, не переписывая всю чертову штуку (чего я бы предпочел не делать). ).
Нужны идеи или информация?
Ваше здоровье
Im not convinced closing the socket will have any effect on the nat traversal
В случаеPAT
действует! - person ρss   schedule 21.09.2015IP + Port number
. АSocket = IP+Port no.
, так что теперь вы видите, что порта нет. эффекты ПАТ. Когда порт закрывается, соответствующая запись PAT удаляется из брандмауэра. Попробуйте superuser.com для лучшего ответа на ваш вопрос! - person ρss   schedule 21.09.2015