- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想在具有静态 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
关于java - UDP 打洞 Java 示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27129268/
我目前正在开发一款在线游戏。在游戏中,需要通过 TCP 和 UDP 将数据从服务器发送到客户端。实现 UDP 打洞很容易,但我不太确定如何实现 TCP 打洞: 服务器:ServerSocket 监听给
我正在尝试使用 mingw 工具链通过 Windows 套接字实现 TCP 打洞。我认为这个过程是正确的,但洞似乎并没有采取。我用了this作为引用。 A 和B 连接到服务器S S 发送给A,B的路由
作者引言 很高兴啊,我们来到了IceRPC之试试的新玩法"打洞",让防火墙哭去吧 试试RPCs的新玩法"打洞" 比较典型的玩法:RPC数据
我目前正在尝试通过 Internet 发送 UDP 消息,并且必须为端点 A 和 B(都位于 NAT 后面)设置防火墙。为此,我想使用 STUN 服务器进行打洞。 当 A 创建对 STUN 服务器的请
实际上,我正在编写一个 Android 应用程序,该应用程序接收连接到电脑的网络摄像头的图片。为了获得更多的 fps,我使用 udp 协议(protocol)而不是 tcp。这个想法是,pc 将图片发
我已经阅读了很多关于如何实现 UDP 打洞的书,但由于某种原因我无法让它工作。 对于那些不熟悉什么是udp打洞的人,这里是我自己的定义: 目标是能够在两个客户端(客户端 A 和客户端 B) 在服务器的
我用 Java 完成了一个在 LAN 范围内运行良好的 P2P 程序,现在我陷入了众所周知的 NAT 穿越问题。我想让我的用户通过 NAT 边界相互连接(我知道不可能 100% 做到这一点)。我已经阅
问题如下。这是我当前没有成功的测试代码。 static void Main(string[] args) { if (args.Count() != 3) { Cons
几周来我一直在尝试创建套接字聊天/文件传输应用程序。我花了几个小时在互联网上搜索一段关于 UDP 打洞的代码,但我没有找到任何有效或足够简单供我使用的代码。 我正在尝试让路由器 (NAT) 后面的两个
我正在做一个客户端-服务器语音聊天程序(非托管 C++,win32),其中客户端使用 TCP 连接到服务器,文本聊天/聊天室功能在 TCP 中完成,而所有音频传输都通过单独的 UDP/RTP 套接字发
stackoverflow 用户! 我有一个必须处理 p2p 的应用程序,这就是我使用 UDP 打洞的方式。但是我在实现时遇到了麻烦。希望你能给我一些提示。 我有服务器,它工作得很好,可以互相介绍客户
我试图用打洞协议(protocol)制作一个服务器客户端。所以我将我的客户端 IP 和客户端端口发送到我的服务器,当第二个用户连接时,服务器向两个客户端发送另一个客户端的 IP 和端口。所以当我有这个
我已经建立了一个网络项目,通过打洞在 LAN 或 WAN 上进行通信。我正在为客户端使用 GCSAsyncUdpSocket。我有一个集合点服务器,它被端口转发,可以从所有传入连接访问。我的设置是这样
我在本地机器上使用以下代码: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream
对于我的学术项目,我正在努力实现这一目标。监听端口 3000 的 Web 服务器 Node JS 应用程序。所以如果你 curl http://localhost:3000 你会得到 Hello Wo
我想在具有静态 IP 的服务器的帮助下对两个客户端进行 UDP 打洞。服务器在端口 7070 和 7071 上等待两个客户端。之后,它向对方发送 IP 地址和端口。这部分工作正常。但是我无法在两个客户
我正在尝试使用 hyperswarm我使用 Node.js API 对我 friend 的计算机进行打洞。 但我不知道从哪里获取该方法所需的参数。 node.holepunch(peer, [call
我一直在寻找一个提供可靠性的简单 UDP C++ 库。我刚刚遇到 ENet,它看起来很完美,只是我在文档中找不到对 NAT 打洞的任何支持。网上好像有几个人在讨论这个问题,但是我还没有找到一个明确的答
我试图通过 NAT 向客户端发送一个 udp 数据包,我们都属于不同的 NAT,我们熟悉 STUN 的理论因此实现这一点的方法是“打洞”我们的通过一个简单的 STUN 服务器.. 基本上服务器只返回外
我是否可以使用部署在 AppEngine 上的 servlet 实现通过 TCP 打洞连接的客户端/服务器网络模型? 如果是这样,您如何将连接请求从客户端转发到主机并建立双向连接,一旦启动就消除服务器
我是一名优秀的程序员,十分优秀!