最近几天,我一直在尝试弄清楚如何通过 UDP 来回发送数据(我有一个简单的多人游戏的计划)。到目前为止一直很好,直到我意识到它只能在 LAN 上正常工作,但没有一个数据包通过 Internet 到达。如果我在一台计算机上运行测试服务器和测试脚本(代码如下)并通过 LAN 发送数据,它就可以正常到达(Wireshark 在通过 Internet 发送时会发出“无法访问端口”错误)。当我在不同的计算机上安装客户端和服务器时,我可以通过 Internet 和 LAN 发送数据,任何东西都不会到达目的地。我花了几个小时谷歌搜索,确保端口被转发,摆弄设置,双重和三次检查代码,用 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))
提前感谢您的帮助。
最佳答案
我刚刚通过 Internet 运行了您的代码,并且运行良好。我使用类型 1 和类型 2 进行测试。 首先,我建议你去掉客户端中的线路绑定(bind)端口。像这样:
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)
因为客户端通常不需要显式绑定(bind)端口——当调用 sock.connect() 时,系统会自动为您的套接字分配一个随机端口。
然后让我们来解决您的问题。 你的代码是正确的,所以肯定是网络出了问题,更可能是服务器出了问题。 如果您的服务器在 NAT 下运行网关或路由器,任何传入连接都将被您的网关拒绝。测试服务器状态的一种简单方法是在命令行提示符下键入 ipconfig(或 Linux 中的 ifconfig)以检查本地 IP 地址是否为公共(public) Internet 地址。公网地址可以从本站获取:whatismyipaddress.com .
这是您最有可能遇到的问题。 使服务器的网络环境正确的最简单方法是找到一个具有静态公网 IP 并且没有任何 NAT 网关的真实服务器。或者只是租用 VPS 来测试您的代码。
谢谢。
关于Python UDP 数据包永远不会到达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22260583/