Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用udp接收不带端口转发的数据_Python_Sockets_Python 3.x_Port - Fatal编程技术网

Python 如何使用udp接收不带端口转发的数据

Python 如何使用udp接收不带端口转发的数据,python,sockets,python-3.x,port,Python,Sockets,Python 3.x,Port,首先,我是一个彻头彻尾的套接字编程高手,所以如果你觉得我做错了什么,请告诉我 所以,我一直在尝试为一个简单的fps游戏编写一个udp服务器 在本地网络上一切正常,但是如果我尝试在互联网上使用我的代码,我确实会遇到一些问题。我的服务器可以从客户端接收数据,消除问题,并可以向客户端发送数据,如果它发送的端口在客户端上打开,如果不是,客户端将不会接收任何数据。(服务器上的端口全部打开)。我现在的问题是,是否有任何方法可以在不需要打开/转发端口的情况下通过Internet接收数据 (client()函数

首先,我是一个彻头彻尾的套接字编程高手,所以如果你觉得我做错了什么,请告诉我

所以,我一直在尝试为一个简单的fps游戏编写一个udp服务器

在本地网络上一切正常,但是如果我尝试在互联网上使用我的代码,我确实会遇到一些问题。我的服务器可以从客户端接收数据,消除问题,并可以向客户端发送数据,如果它发送的端口在客户端上打开,如果不是,客户端将不会接收任何数据。(服务器上的端口全部打开)。我现在的问题是,是否有任何方法可以在不需要打开/转发端口的情况下通过Internet接收数据

(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这只是代码的一部分,但我认为它是相关的。
如果在我发送/接收数据的方式中,不需要打开/转发端口就无法接收数据,请建议一种可以实现此目的的方法(如果有的话)。

看看UDP打孔:

基本前提是客户机首先连接到服务器,并在NAT路由表中创建一个条目。然后服务器查看请求,查看NAT路由器用于发送请求的端口。您应该能够将UDP数据包发送到此端口,然后将其转发到专用网络中的客户端

总之,不要将端口硬编码到
3560
。您需要根据UDP数据包的来源更改此端口


您可能还想考虑使用TCP(基于连接的协议)(UDP是无连接的)——当从客户端到服务器建立连接时,很容易在这个连接上来回发送数据。

< P>作为这个问题,很难找到一个明确的答案,当我开始工作时,感谢Martin Konecny对打孔的解释(例如。 ),但也要感谢我自己多次“尝试和错误”的尝试


我哪里做错了哪里最有可能的事实是,我关闭了客户端上的套接字,该套接字用于发出sendto调用,然后尝试在新套接字上侦听服务器的应答。这不起作用,或者至少我没有让它起作用。但是,如果我不关闭插座,并在我用来拨打sendto电话的同一个插座上聆听回答,那么一切都会正常工作。事实证明,我甚至不需要像我在问题中所做的那样绑定套接字以使其工作。

好的,这让我有了更多的理解,但是我不理解客户端如何知道它应该绑定到哪个端口(或者可能不需要绑定?)。我正在使用socket.sendto方法向服务器发送数据,这个方法使用的是随机的?端口每次,我都可以很容易地让服务器响应这个随机端口(在接收数据的同一个端口上响应),但是我如何让客户端在这个端口上查找答案呢?因为每次调用都是随机的,我需要重新绑定它吗?在客户端,如何获取上次sendto调用时使用的端口?