Я проделал некоторое чтение об обходах UDP NAT, и я уверенно понимаю, что я понимаю основы, но я все еще боюсь реализации.python server-client nat traversal
В моем проекте имеется глобально доступный сервер и клиенты позади nat. Его игра с базовым запросом join_game отправляет с клиента на сервер, а затем сервер отправляет обновления каждый интервал. Я тестировал дома и забыл, что у меня есть DMZ на моем маршрутизаторе, и он работал нормально. Я отправил это друзьям для тестирования, и они не могут получать обновления с сервера.
Вот текущая методология, все пакеты UDP:
- Клиент открывает сокет и посылает запрос на подключение к серверу.
- Сервер получает запрос и ответный адрес сообщения и отвечает клиенту: да, вы можете присоединиться, и, кстати, я буду отправлять обновления вашего ответа на ip/port, который выглядит следующим образом: ,
- Клиент улавливает ответ, затем закрывает сокет и запускает прослушивающий класс прослушивателя UDP, чтобы прослушать ответ-порт, о котором нам рассказал сервер.
- Затем клиент захватывает обновляемые обновления сервера и обрабатывает их по мере необходимости. Время от времени клиент открывает новый сокет и отправляет пакет UDP с обновлением на сервер (какие клавиши нажаты и т. Д.).
Мое понимание - это ответный адрес, который получает сервер, должен иметь правильный порт для перемещения 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
Друг упомянул, что, возможно, когда я отправлю запрос на соединение, то получите ответ, который я не должен закрывать сокет. Держите этот разъем живым и сделайте это слушателем. Я не уверен, что закрытие сокета будет иметь какое-то влияние на обходные пути, и я не знаю, как создать нерелевантный прослушиватель udp, который берет уже существующий сокет, не переписывая всю проклятую вещь (что я бы предпочел не).
Какие-либо идеи или информация требуется?
Приветствия
Обычно NAT выполняется маршрутизатором/брандмауэром. Клиент не имеет ничего общего с NAT, на самом деле клиент просто знает, куда отправлять все эти пакеты. Я не знаю, какая у вас настройка сети? Может быть, маршрутизатор/брандмауэр на сторонах вашего друга неправильно настроен для выполнения NAT? Какой тип NAT это? Как вы проверили дома? Был ли сервер и клиент в локальной сети с маршрутизатором между ними? «Я не уверен, что закрытие сокета будет иметь какое-то влияние на прохождение nat». В случае «PAT» это срабатывает! –
У моих друзей стандартный маршрутизатор/модем, который вы получаете бесплатно с любым интернет-пакетом. Обычный интернет в модем, базовая ЛВС в доме. То же, что и моя настройка, за исключением того, что я включил DMZ для своей машины. Выключение DMZ заставило его перестать работать. Питон был упакован в исполняемый файл pyinstaller, и когда вы запустите его, Win7 просит разрешения подключить его к сети (которую они приняли). Я запускал его исключительно из сценариев, а также на моей машине без DMZ, и это не работает. В наших сетевых настройках нет ничего необычного :( – Oliver
Что вы имеете в виду, в случае использования PAT? – Oliver