2014-08-20 3 views
0

Во-первых, я полный нуб в программировании сокетов, поэтому PLZ скажите мне, если вы верите, что я делаю что-то неправильно.Как извлечь данные из переадресации портов с помощью udp

Итак, я пытался запрограммировать udp-сервер для простой игры fps.

В локальных сетях все работает нормально, если я пытаюсь использовать мой код в Интернете, я действительно получаю некоторые проблемы. мой сервер может получать данные от проблем с белыми клиентами и может отправлять данные клиентам, если порт, который он отправляет, открыт на клиенте, если он не является клиентом, он не получит никаких данных. (порты на сервере открыты). мой вопрос сейчас, есть ли способ получить данные через Интернет без необходимости открытия/пересылки порта?

(клиент() функция постоянно повторяется в цикле)

мой код для приема данных выглядит следующим образом:

import socket 

server_IP = 'ip of server' 
Client_port = 3560 
Server_port = 5000 
Client_socket = None 
First_run = True 
first = True 

def client(): 
    global server_IP 
    global Client_port 
    global Server_port 
    global Client_socket 
    global first 
    if first == True: 
     try: 
      local = ('', Client_port) 
      host = (server_IP, Server_port) 
      Client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
      Client_socket.bind(local) 
      Client_socket.setblocking(False) 
      first = False 
     except: 
      print("Failed") 
    try: 
     data, connection = Client_socket.recvfrom(512) 
    except socket.error: 
     return 
    if data: 
     #irrelevant code handling the data... 

и код сервера посыла является запирающим как это:

import socket 
server_socket = None 
server_port = 5000 
Data_Port = 3560 
print("importing the socket...") 
try: 
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
except socket.error as msg: 
    server_socket = None 
try: 
    server_socket.bind(("", server_port)) 
except socket.error as msg: 
    server_socket.close() 
    server_socket = None 
if server_socket is None: 
    print('could not open socket') 
    ret = False 
server_socket.sendto(Data_to_Send, ('client ip here',Data_Port)) 

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

ответ

1

Посмотрите на UDP перфорирования:

http://en.wikipedia.org/wiki/UDP_hole_punching

Основной предпосылкой является то, что клиент подключается к серверу первого создания записи в таблице маршрутизации NAT. Затем сервер просматривает запрос, чтобы узнать, какой порт NAT-маршрутизатор использовал для отправки запроса. Вы должны иметь возможность отправлять UDP-пакет на этот порт, который затем должен быть отправлен клиенту в частной сети.

Итак, не суммируйте свой порт до 3560. Вам необходимо изменить этот порт на основе того, откуда пришел пакет UDP.

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

+0

в порядке, это дало мне больше понимания, я, однако, не понимаю, как клиент должен знать, к какому порту он должен привязываться (или maby ему не нужно связывать?). Я использую метод socket.sendto для отправки данных на сервер, этот метод использует случайный?порт каждый раз, я могу легко заставить сервер реагировать на этот случайный порт (отвечать на тот же порт, на который он получил данные), но как я могу заставить клиента искать ответ на этом порту ?, поскольку он случайный каждый мне нужно переустановить его при каждом звонке? и как я могу, на клиенте получить порт, используемый при последнем вызове sendto? – user3416789

0

как этот вопрос, где трудно найти ясный ответ и как я получил его на работу, благодаря объяснению, данному Мартином Конечни на пробивке отверстий (например, http://en.wikipedia.org/wiki/UDP_hole_punching), но также благодаря моим собственным "попыткам -and-error ".

Что я делаю неправильно, где, скорее всего, тот факт, что я закрываю сокет на клиенте тем, где используется для отправки вызова sendto, а затем пытается прослушивать ответ с сервера в новом сокете. это не работает, или, по крайней мере, я не получил его на работу. Если я не закрыл сокет и слушал ответ в том же сокете, что использовал для вызова sendto, все работало нормально. Оказалось, что мне даже не нужно связывать сокет, как я делаю в вопросе, чтобы это работало.

Смежные вопросы