首先,我是套接字编程中的一个完整的菜鸟,所以请告诉我你是否做错了什么。
所以,我一直在尝试为一个简单的fps游戏编写一个udp服务器。
在本地网络上一切正常,如果我尝试在互联网上使用我的代码我确实遇到了一些问题。我的服务器可以从客户端白化问题中接收数据,并且如果客户端不能接收任何数据,则在客户端上打开它所发送的端口时,可以向客户端发送数据。 (服务器上的端口全部打开)。我现在的问题是,有没有办法通过互联网接收数据而无需打开/转发端口?
(client()函数在循环中不断重复)
我接收数据的代码如下:
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))
ofc这只是代码的一部分,但我认为它是相关的。 如果无法以我发送/接收数据的方式接收数据而无需开放/转发端口,PLZ建议一种方法可以做到这一点,如果有的话。
答案 0 :(得分:1)
看看UDP打孔:
http://en.wikipedia.org/wiki/UDP_hole_punching
基本前提是客户端首先在NAT路由表中创建条目,然后连接到服务器。然后,服务器查看请求以查看NAT路由器用于发送请求的端口。您应该能够将UDP数据包发送到此端口,然后将该数据包转发到专用网络中的客户端。
总而言之,请勿将您的端口硬编码为3560
。您需要根据UDP数据包的来源更改此端口。
您可能还想考虑使用TCP,这是一种基于连接的协议(UDP是无连接的) - 当从客户端到服务器建立连接时,很容易在此上来回发送数据连接。
答案 1 :(得分:0)
因为这个问题很难找到一个明确的答案,因为我得到了它的工作,这要归功于Martin Konecny对打孔的解释(例如。 http://en.wikipedia.org/wiki/UDP_hole_punching),但也感谢我自己的许多"尝试和错误"尝试。
我在哪里做错了很可能是我关闭客户端上的套接字的事实,用于进行sendto调用,然后尝试在新套接字上侦听来自服务器的答案。这不起作用,或者至少我没有得到它的工作。但是,如果我没有关闭套接字,并在我用来发送调用的同一个套接字上听取了答案,那么一切正常。事实证明,我仍然需要绑定套接字,因为我正在为此工作提出问题。