当前位置: 首页 > 知识库问答 >
问题:

跨NAT的UDP客户端无法从服务器接收数据

洪弘毅
2023-03-14

我正在尝试使用UDP在服务器(在公共IP上)和客户端(通过NAT)之间进行双向通信。我的逻辑是,如果服务器向IP和它接收数据包的端口发送一些数据,客户端仍然应该得到它,因为NAT最终会有将数据包发送到客户端的映射。

客户端有 2 个进程,一个用于发送数据包,另一个进程用于接收数据。服务器继续等待数据,如果它获得数据,它会将数据发送回从接收数据的端口和 IP。

客户代码如下:

client_recv.py

import socket
import sys

UDP_IP = '0.0.0.0'#my ip address in the local network
UDP_PORT = 5000

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)
    print ("received message:" + data)

客户端发送.py

import socket
import time
import sys

UDP_IP = 'XXXXXXX.com'#external server IP address
UDP_PORT = 4000
MESSAGE = "Hi!"

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 5000))
i = 0
while True:
    sock.sendto(MESSAGE + ' # ' + str(i), (UDP_IP, UDP_PORT))
    time.sleep(1)
    i = i + 1

服务器(在XXXXX.com上-公共IP)获取数据包,但不获取客户端。下面是在服务器上接收和发送数据包的代码

服务器发送接收

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('0.0.0.0', 4000))

while True:
    data, inetaddr = sock.recvfrom(1024)
    print('Received ' + data)
    (ip, port) = inetaddr
    print("IP:"+str(ip)+",Port:"+str(port))
    sock.sendto('Hi From Server (against ' + data + ')', (ip, port))

编辑 1:

如答案中所述,必须使用相同的套接字,所以我做了以下操作,它起作用了。但是,我仍然不清楚为什么绑定到客户端上同一端口的不同套接字 (client_recv) 不起作用。由于重复使用相同的端口,因此client_recv应该可以正常工作吗?为什么它失败了,是什么让客户端上发送和接收的相同套接字起作用?

client_send_recv.py

import socket
import time
import sys

UDP_IP = 'twig-me.com'#external server IP address
UDP_PORT = 4000
MESSAGE = "Hi!"

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 5000))
i = 0
while True:
    print ("Sending message:" + str(i))
    sock.sendto(MESSAGE + ' # ' + str(i), (UDP_IP, UDP_PORT))
    time.sleep(1)
    i = i + 1
    data, addr = sock.recvfrom(1024)
    print ("received message:" + data)

共有1个答案

申屠裕
2023-03-14

TL;TR:这个问题与NAT无关。相反,它是关于不太具体的vs,。套接字上更具体的绑定。

同一系统上有两个客户端

    client_recv.pl绑定到 0.0.0.0
  • UDP_IP = '0.0.0.0
    '#my本地网络中的 IP 地址
  • client_send.pl最初也显式绑定到 0.0.0.0:
  • sock.bind(('0.0.0.0
    ', 5000))
    但是套接字将在内部重新绑定到本地系统的传出 IP,以便使用正确的传出 IP 地址发送数据包::
    sock.sendto(MESSAGE ' # ' str(i), (UDP_IP, UDP_PORT))
    请注意,您无法在 netstat 中看到此新绑定, 它似乎在内核中更深。

这意味着您最终有两个套接字:

    < li>client_recv.pl有一个绑定到0.0.0.0:5000的套接字 < li>client_send.pl有一个套接字绑定到您的-local-ip:5000

如果一个数据包从服务器到达,它将转到最特定的套接字,即client_send.pl中的一个套接字。因此client_recv。pl从不接收数据包。

如果您改为将 IP 地址client_recv.pl更改为本地系统的 IP,您将获得两个套接字,都绑定到 your-local-ip:5000。由于在这种情况下没有最具体的套接字,因此数据包实际上被传送到第一个读取它的套接字,在您的情况下client_recv.pl

 类似资料:
  • 我想做的是: 为了学习游戏编程,我使用专用服务器和UDP创建了一个回声设置。专用服务器在不同的城市(也就是不在我的本地网络中)。 在我的本地计算机上,我有一个udp客户端和服务器(两个不同的程序)。当我第一次启动python服务器时,windows防火墙立即询问我是否要添加异常。在允许我的python服务器联网之后,我仍然没有收到任何消息。(客户- 我的问题是: 游戏如何解决这个问题?我没有为我想

  • 我开发了一个客户端-服务器UDP应用程序。服务器UDP套接字设置为广播UDP套接字。双方的代码不会产生任何错误,但客户端未接收到从广播UDP服务器端发送的消息。请看一下我的代码,我知道有一些错误我想不通。我真的需要帮助: 服务器: 客户: }

  • 我尝试使用Spring Integration实现UDP服务器,就像这里描述的那样,但是当客户端在NAT之后运行时,它们将永远不会收到来自服务器的响应。这是因为服务器应该从与UDP适配器端口相同的端口发送响应数据报(通过这里解释的NAT检查UDP)。 如何使用Spring Integration实现与NAT后客户端的正确UDP通信?

  • 我是一个使用python进行套接字编程的初学者。我正在做我的课程项目。我的项目的一部分需要用不同的端口发送和接收UDP消息。提供了名为robot的服务器程序,我需要编写名为student的客户端程序,它可以与机器人进行交互。因此,我不能显示服务器程序中的所有源代码。 这是服务器程序中与UDP套接字相关的部分 这是我的客户端程序。s3 是 UDP 套接字。我可以成功地向服务器程序发送消息,但无法从中

  • 客户端-NAT后面的Windows桌面,运行UDP客户端应用程序。 服务器-具有公共IP的Ubuntu服务器,运行一个UDP服务器应用程序,该应用程序期望在端口6000上发送数据包。 ClientPrivate/Public-客户端的私有/公共IP 服务器私有/公共 - 服务器的私有/公共 IP 客户端打开一个UDP套接字Client私人: 777和发送数据报Server公共: 6000 服务器从

  • 我有一个示例代码如下,套接字绑定到IP10.10.88.11和端口9876。我用下面的wireshark测试了2种情况。两台电脑都在同一个子网中。 从同一PC发送UDP数据包(10.10.88.11)-UDP服务器能够接收 从另一台电脑发送UDP数据包(10.10.88.10)-UDP服务器无法接收,但Wireshark(在10.10.88.11)能够捕获数据包 我在网上搜索过,但找不到解决办法。