UDP-пакеты Python никогда не приходят

Последние пару дней я провел, пытаясь понять, как отправлять данные туда и обратно по UDP (у меня есть планы на простую многопользовательскую игру). Пока все хорошо, пока я не понял, что он отлично работает только через локальную сеть, но ни один из пакетов никогда не приходит через Интернет. Если я запускаю тестовый сервер и тестовый скрипт (код ниже) на одном компьютере и отправляю данные по локальной сети, они поступают нормально (Wireshark выдает ошибку «Порт недоступен» при отправке через Интернет). Когда у меня есть клиент и сервер на разных компьютерах, я могу отправлять данные через Интернет и локальную сеть, но ничего не приходит к месту назначения. Я часами гуглил, убеждался, что порты переадресованы, возился с настройками, дважды и трижды проверял код, проверял с помощью Wireshark, тестировал с другими людьми, ничего.

Что я делаю неправильно?

Вот мой тестовый код:

import socket, pickle
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock.setblocking(0)
port = 5000

type = raw_input("1=Server 2=Client 3=Local Client: ")

if type == "1":
  ip = ""
  sock.bind((ip,port))
  print("Socket: "+str(sock.getsockname()))
  while True:
    try:
      rdata, addr = sock.recvfrom(1024)
      data = pickle.loads(rdata)
      print addr, ">>>", data
    except:
      pass

elif type == "2":
  ip = "79.222.132.25"
  sock.bind(("192.168.2.102",port+1))
  sock.connect((ip,port))
  print("Socket: "+str(sock.getsockname()))
  print("Connected to: "+str(sock.getpeername()))
  while True:
    input = raw_input("Send:")
    data = pickle.dumps((input))
    sock.send(data)

else:
  ip = "192.168.2.102"
  sock.bind((ip,port+1))
  while True:
    input = raw_input("Send:")
    data = pickle.dumps((input))
    sock.sendto(data,(ip,port))

Спасибо за помощь заранее.


person Doctor Jaska    schedule 07.03.2014    source источник
comment
Нередко можно увидеть что-то в Wireshark, но оно все еще не работает. Wireshark разрешает все пакеты. Вы пробовали цикл for на принимающей стороне?   -  person Drewness    schedule 08.03.2014
comment
Даже если вы попытаетесь подключиться к своему интернет-адресу, это должно сработать. Это напоминает мне перфорацию отверстий UDP, которую я пробовал с другом, и она работала через Интернет. Хотя у нас были разные интернет-адреса. Вы уверены, что ваш маршрутизатор перенаправляет весь udp-трафик с порта 5000 на порт 5000 вашего компьютера? Может быть, вы можете попробовать связаться с собой извне и с другого ip.   -  person User    schedule 08.03.2014
comment
Никогда не извлекайте случайные данные из Интернета. Прочитайте предупреждение вверху docs.python.org/2/library/pickle.html. .   -  person Jean-Paul Calderone    schedule 08.03.2014


Ответы (1)


Я только что запустил ваш код через Интернет и отлично работает. Я использовал тип 1 и 2 для тестирования. Во-первых, я рекомендую вам удалить порт привязки линии в клиенте. Так:

elif type == "2":
ip = "79.222.132.25"
# sock.bind(("192.168.2.102",port+1))
sock.connect((ip,port))
print("Socket: "+str(sock.getsockname()))
print("Connected to: "+str(sock.getpeername()))
while True:
    input = raw_input("Send:")
    data = pickle.dumps((input))
    sock.send(data)

Поскольку обычно клиенту не нужно явно привязывать порт - при вызове sock.connect() система автоматически назначит случайный порт вашему сокету.

Тогда давай решим твою проблему. Ваш код правильный, значит, что-то не так с Интернетом, скорее всего, с сервером. Если ваш сервер работает под шлюзом NAT или маршрутизатором, любое входящее соединение будет отклонен вашим шлюзом. Простой способ проверить состояние вашего сервера — ввести ipconfig (или ifconfig в Linux) в командной строке, чтобы проверить, является ли локальный IP-адрес общедоступным интернет-адресом. Публичный интернет-адрес можно получить с этого веб-сайта: whatismyipaddress.com.

Это самая вероятная проблема, с которой вы можете столкнуться. Самый простой способ сделать сетевое окружение сервера правильным — найти настоящий сервер со статическим общедоступным IP-адресом и без шлюза NAT. Или просто арендуйте VPS для тестирования своего кода.

Спасибо.

person Laohyx    schedule 08.03.2014
comment
Не привязывая клиентский сокет вручную, он действительно работает с Hamachi. Спасибо! - person Doctor Jaska; 08.03.2014