gpt4 book ai didi

java - UDP 打洞 Java 示例

转载 作者:搜寻专家 更新时间:2023-10-30 21:11:39 25 4
gpt4 key购买 nike

我想在具有静态 IP 的服务器的帮助下对两个客户端进行 UDP 打洞。服务器在端口 7070 和 7071 上等待两个客户端。之后,它向对方发送 IP 地址和端口。这部分工作正常。但是我无法在两个客户之间建立通信。我在不同的 Wifi 网络和 3G 移动网络中尝试了代码。客户端程序抛出 IO-Exception“No route to host”。客户端代码用于两个客户端。一次使用端口 7070 执行,一次使用 7071。

您认为我是否正确地实现了 UDP 打洞概念?有什么想法让它发挥作用吗?首先是服务器代码,然后是客户端代码。

谢谢你的帮助。

服务器代码:

public class UDPHolePunchingServer {

public static void main(String args[]) throws Exception {

// Waiting for Connection of Client1 on Port 7070
// ////////////////////////////////////////////////

// open serverSocket on Port 7070
DatagramSocket serverSocket1 = new DatagramSocket(7070);

System.out.println("Waiting for Client 1 on Port "
+ serverSocket1.getLocalPort());

// receive Data
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket1.receive(receivePacket);

// Get IP-Address and Port of Client1
InetAddress IPAddress1 = receivePacket.getAddress();
int port1 = receivePacket.getPort();
String msgInfoOfClient1 = IPAddress1 + "-" + port1 + "-";

System.out.println("Client1: " + msgInfoOfClient1);

// Waiting for Connection of Client2 on Port 7071
// ////////////////////////////////////////////////

// open serverSocket on Port 7071
DatagramSocket serverSocket2 = new DatagramSocket(7071);

System.out.println("Waiting for Client 2 on Port "
+ serverSocket2.getLocalPort());

// receive Data
receivePacket = new DatagramPacket(new byte[1024], 1024);
serverSocket2.receive(receivePacket);

// GetIP-Address and Port of Client1
InetAddress IPAddress2 = receivePacket.getAddress();
int port2 = receivePacket.getPort();
String msgInfoOfClient2 = IPAddress2 + "-" + port2 + "-";

System.out.println("Client2:" + msgInfoOfClient2);

// Send the Information to the other Client
// /////////////////////////////////////////////////

// Send Information of Client2 to Client1
serverSocket1.send(new DatagramPacket(msgInfoOfClient2.getBytes(),
msgInfoOfClient2.getBytes().length, IPAddress1, port1));

// Send Infos of Client1 to Client2
serverSocket2.send(new DatagramPacket(msgInfoOfClient1.getBytes(),
msgInfoOfClient1.getBytes().length, IPAddress2, port2));

//close Sockets
serverSocket1.close();
serverSocket2.close();
}

客户端代码

public class UDPHolePunchingClient {

public static void main(String[] args) throws Exception {
// prepare Socket
DatagramSocket clientSocket = new DatagramSocket();

// prepare Data
byte[] sendData = "Hello".getBytes();

// send Data to Server with fix IP (X.X.X.X)
// Client1 uses port 7070, Client2 uses port 7071
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, InetAddress.getByName("X.X.X.X"), 7070);
clientSocket.send(sendPacket);

// receive Data ==> Format:"<IP of other Client>-<Port of other Client>"
DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
clientSocket.receive(receivePacket);

// Convert Response to IP and Port
String response = new String(receivePacket.getData());
String[] splitResponse = response.split("-");
InetAddress ip = InetAddress.getByName(splitResponse[0].substring(1));

int port = Integer.parseInt(splitResponse[1]);

// output converted Data for check
System.out.println("IP: " + ip + " PORT: " + port);

// close socket and open new socket with SAME localport
int localPort = clientSocket.getLocalPort();
clientSocket.close();
clientSocket = new DatagramSocket(localPort);

// set Timeout for receiving Data
clientSocket.setSoTimeout(1000);

// send 5000 Messages for testing
for (int i = 0; i < 5000; i++) {

// send Message to other client
sendData = ("Datapacket(" + i + ")").getBytes();
sendPacket = new DatagramPacket(sendData, sendData.length, ip, port);
clientSocket.send(sendPacket);

// receive Message from other client
try {
receivePacket.setData(new byte[1024]);
clientSocket.receive(receivePacket);
System.out.println("REC: "
+ new String(receivePacket.getData()));

} catch (Exception e) {
System.out.println("SERVER TIMED OUT");
}
}

// close connection
clientSocket.close();
}

更新该代码通常可以正常工作。我现在已经在两个不同的家庭网络中尝试过它并且可以正常工作。但它在我的 3G 或大学网络中不起作用。在 3G 中,我验证了 NAT 再次将两个端口(客户端端口和路由器分配的端口)映射在一起,即使在关闭和打开 clientSocket 之后也是如此。有谁知道为什么它不工作呢?

最佳答案

UDP 打洞并不是所有类型的 NAT 都可以实现的。没有为所有类型的 NAT 定义通用或可靠的方法。对称NAT更是难上加难。

根据 NAT 行为,发送 UDP 数据包的不同设备的端口映射可能不同。比如,如果 A 向 B 发送一个 UDP 数据包,它可能会得到一些端口,比如 50000。但是如果 A 向 C 发送一个 UDP 数据包,那么它可能会得到一个不同的映射,比如 50002。所以,在你的情况下,向服务器发送一个数据包可能给客户端一些端口,但向其他客户端发送数据包可能会提供其他端口。

您应在此处阅读有关 NAT 行为的更多信息:

https://www.rfc-editor.org/rfc/rfc4787

https://www.rfc-editor.org/rfc/rfc5128

UDP hole punching not going through on 3G

关于java - UDP 打洞 Java 示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27129268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com