使用 NAT 将 UDP 数据包发送到 IP

Send UDP packets to IP with NAT

我有一个服务器 运行 public IP,没有 NAT。它接收 UDP 数据包,我想将它们发送到连接的每个客户端。

一个或多个客户端将在 NAT 后面。

我读过有关 UDP 打孔的内容,但它似乎并不完全是我想要的。我不是要从客户端发送到客户端。我希望数据流从客户端 -> 服务器 -> 所有客户端。

客户

// Init TCP Socket
connection = new Socket(connectionAddress, 54540);

// Create receive socket
DatagramSocket socketReceive = new DatagramSocket(54541);

服务器


// Receive socket
receiveAudioSocket = new DatagramSocket(54541);

// Thread to handle new received packets
ServerAudioReceiverWorker audioReceiverWorker = new ServerAudioReceiverWorker(receiveAudioSocket, this);
audioReceiverWorker.start();

// TCP Socket
serverSocket = new ServerSocket(54540);
System.out.println("Server has started");

这是我的客户端服务器的基本设置。

我预计如果我从客户端向服务器发送一个 UDP 数据包 public IP。路由器会在客户端网络上为端口 54541 添加 NAT 规则,以接收从服务器发送回客户端 public IP 和端口 54541 的 UDP 数据包。它似乎不是那样工作的。

我想那是因为被分配的 NAT 规则被赋予了一个特定的端口,用于请求 public IP 以本地 IP 为目标。我不确定如何找到服务器应该为每个客户端发送数据包的端口。

是否需要使用UPnP打开客户端网络上的端口,让服务器知道向哪个端口发送数据包。

NAT 要求 NAT 路由器后面的客户端首先发起到外部服务器的连接,以便 NAT 路由器可以为地址和端口转换创建状态。来自服务器的回复必须与状态完全匹配,否则 NAT 路由器无法完成转换。

这意味着:

  • 您必须在客户端中使用相同的套接字进行发送和接收,即您不能期望在与当前不同的端口上返回回复。
  • 服务器必须将消息发送到与客户端用作源以联系服务器的完全相同的 IP 和端口,并且必须从与客户端用作目标的完全相同的 IP 和端口发送 - 这通常通过在服务器上使用相同的套接字来完成。
  • 无法向最近未联系过服务器的客户端发送消息,因为在这种情况下,客户端 NAT 路由器中没有匹配状态(它会在一段时间后过期)。