如何使用udp在没有端口转发的情况下接收数据

时间:2014-08-20 22:03:24

标签: python sockets python-3.x port

首先,我是套接字编程中的一个完整的菜鸟,所以请告诉我你是否做错了什么。

所以,我一直在尝试为一个简单的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建议一种方法可以做到这一点,如果有的话。

2 个答案:

答案 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调用,然后尝试在新套接字上侦听来自服务器的答案。这不起作用,或者至少我没有得到它的工作。但是,如果我没有关闭套接字,并在我用来发送调用的同一个套接字上听取了答案,那么一切正常。事实证明,我仍然需要绑定套接字,因为我正在为此工作提出问题。