早就听说用UDP穿透NAT可以解决P2P软件中的两个通过NAT上网的客户端直接通信的问题。当然,需要一个中介来帮助找到对方。终于用Java做了这个试验。
代码贴出来吧。
UDPAgent.java:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.regex.Pattern;
/**
*
* @author Leo Luo
*
*/
public class UDPAgent implements Runnable {
public static void main(String[] args) throws Exception {
new UDPAgent(-1).start();
}
DatagramSocket ds;
byte[] recbuf = new byte[1024];
DatagramPacket rec = new DatagramPacket(recbuf, recbuf.length);
static String ipPattern = "([0-9]{1,3}.){3}[0-9]{1,3}";
static String portPattern = "[0-9]{1,5}";
static Pattern sendPattern = Pattern.compile("send " + ipPattern + " "
+ portPattern + " .*");
int port;
public UDPAgent(int port) {
this.port = port;
}
public void init() throws Exception {
if (port < 1024 || port > 655535) {
ds = new DatagramSocket();
} else {
ds = new DatagramSocket(port);
}
}
public void start() throws Exception {
println("start");
println("LocalPort:" + port);
init();
new Thread(this).start();// recive thread
receive();
}
public void receive() {
for (;;) {
try {
ds.receive(rec);
String msg = new String(rec.getData(), rec.getOffset(), rec
.getLength());
String line = rec.getSocketAddress() + ":" + msg;
println(line);
onReceive(rec);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void onReceive(DatagramPacket rec) {
}
public void doCommand(String cmd) throws Exception {
// command:
// 1. send xxx.xxx.xxx.xxx xxx *******************
if (sendPattern.matcher(cmd).matches()) {
doSend(cmd);
}
}
public void doSend(String cmd) throws Exception {
println("CMD: " + cmd);
String[] s = cmd.split(" ", 4);
int port = Integer.parseInt(s[2]);
InetSocketAddress target = new InetSocketAddress(s[1], port);
byte[] bs = s[3].getBytes();
doSend(target, bs);
}
public void doSend(SocketAddress addr, byte[] data) throws Exception {
DatagramPacket pack = new DatagramPacket(data, data.length, addr);
ds.send(pack);
}
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
try {
String line = reader.readLine();
while (!"exit".equals(line)) {
doCommand(line);
line = reader.readLine();
}
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
public void println(String s) {
System.out.println(System.currentTimeMillis() + ":" + s);
}
}
UDPClient.java
____________________________________________________
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
public class UDPClient extends UDPAgent {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
new UDPClient("www.javadoc.cn", 2008, -1).start();
}
String serverName;
int serverPort;
SocketAddress server;
public UDPClient(String host, int port, int localPort) {
super(localPort);
this.server = new InetSocketAddress(host, port);
}
public void start() throws Exception {
println("start");
init();
register();
new Thread(this).start();// recive thread
receive();
}
public void onReceive(DatagramPacket rec) {
try {
report(rec);
if (rec.getSocketAddress().equals(server)) {
doCommand(new String(rec.getData(), rec.getOffset(), rec
.getLength()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void report(DatagramPacket rec) throws Exception {
String s = rec.getSocketAddress()
+ new String(rec.getData(), rec.getOffset(), rec.getLength());
byte[] buf = s.getBytes();
ds.send(new DatagramPacket(buf, buf.length, server));
}
public void register() throws Exception {
String msg = "register " + getLocalAddress() + " " + ds.getLocalPort();
doSend(server, msg.getBytes());
}
public String getLocalAddress() throws Exception {
InetAddress addr = InetAddress.getLocalHost();
return addr.getHostAddress();
}
}
UDPServer.java
_______________________________________________________________
public class UDPServer extends UDPAgent {
public static void main(String[] args) throws Exception {
new UDPServer(2008).start();
}
public UDPServer(int port) {
super(port);
}
}
1。启动一个Server.
2。启动两个Client.
然后从Server端的Console里边可以看到两个Client的NAT后的地址和端口。
在Server段输入命令 send a.a.a.a A send b.b.b.b B hello
a.a.a.a是第一个Client的NAT后的ip,A端口号。
b是第二个。。。
输入这个命令后,A就会直接发给B一个 hello。 发送成功。 如果是同一个NAT后边,可能要让A发送到B的内网地址才能成功。
分享到:
相关推荐
Java提供了一种方式来实现UDP NAT穿透,通过创建一个服务器端和客户端应用程序,可以协助位于NAT后的设备之间建立直接通信。以下是实现这一技术的一些关键知识点: 1. **STUN(Traversal Using Relays around NAT)...
在Java中实现NAT穿越,主要是利用STUN(Session Traversal Utilities for NAT)协议或者ICE(Interactive Connectivity Establishment)协议。STUN服务器可以用来帮助客户端发现其公网IP和端口,而ICE则是一种更为...
总结,通过Java实现的UDP打洞技术,可以克服NAT的障碍,实现子网间的P2P通信。这在分布式系统、在线游戏、文件共享等领域都有广泛应用。在实际开发中,还需要考虑兼容性、安全性以及网络环境的复杂性。
Java中的NAT实现主要涉及到网络编程,尤其是在处理分布式系统、P2P网络或者需要穿透NAT的场景时。Java提供了一些API来处理这些问题,如MulticastSocket和DatagramSocket,它们可以帮助开发者发送和接收UDP数据包,...
【标签】"java"和"java_nat"进一步确认了这个压缩包的内容是以Java编程语言实现的NAT相关的程序。Java是一种广泛使用的面向对象的编程语言,以其“一次编写,到处运行”的特性著称,适合开发跨平台的网络应用。 ...
Java中的"stun4j"库是一个用于STUN和TURN(Traversal Using Relays around NAT)服务的客户端库,提供了处理NAT穿透所需的基本功能。开发者可以使用stun4j来创建STUN请求,解析响应,从而获取到必要的网络信息。 ...
stun4j是Java编程语言中实现STUN协议的一个开源库,它为开发者提供了简单易用的API,以便在Java应用中集成NAT穿透功能。stun4j包含了以下主要组件和功能: 1. **STUN客户端(STUNClient)**:这是核心组件,负责...
标题“NAT穿透Java”指的是在Java编程环境中实现网络地址转换(NAT)穿透的技术,主要针对UDP协议。NAT穿透对于实现内网设备之间的通信至关重要,因为常规的NAT设置会阻止直接的端对端连接。在此场景下,描述中提到...
为此,探讨 NAT 种类、应用及核心思想,及用 Java 网络包 java.net 实现 NAT 软交换的思路和方法,并根据网络存储系统安全问题,提出基于 NAT 的存储集群架构,分析其运行机制算法。模拟测试结果表明,基于 NAT 可在...
"JAVA穿越NAT"这一主题涉及到了如何在Java环境中实现在网络地址转换(Network Address Translation, NAT)下的点对点(P2P, Peer-to-Peer)UDP通信。NAT通常被用来让多个内部网络设备共享一个公共IP地址访问外部网络...
本文研究基于Java的NAT软交换代理及存储集群系统,讨论了NAT的种类、应用及核心思想,并使用Java网络包java.net实现了NAT软交换的思路和方法。同时,根据网络存储系统安全问题,提出了基于NAT的存储集群架构,分析了...
在提供的压缩包中,"P2P之UDP穿透NAT的原理与实现源代码"很可能是用某种编程语言(如C++、Python或Java)实现的示例代码,包含具体的打洞算法和信令交互逻辑。通过阅读和理解这些代码,可以更深入地了解UDP穿透NAT的...
就是非常有名的“UDP打洞技术”,UDP打洞技术依赖于由公共防火墙和cone NAT,允许适当的有计划的端对端应用程序通过NAT“打洞”,即使当双方的主机都处于NAT之后。这种技术在 RFC3027的5.1节[NAT PROT] 中进行了重点...
而“stund”可能是指STUN服务器的实现,通常是一个守护进程(daemon),负责处理来自客户端的STUN请求。 总的来说,这个压缩包包含的源代码可能是用于创建一个工具,该工具能够自动检测用户所在的NAT类型,这将有助...
JSTUN,全称为Java Simple Traversal of User Datagram Protocol (UDP) Through NAT,是Java语言编写的一个STUN(简单穿越NAT)协议的实现。STUN是一种IETF标准,它允许内网设备发现其在公网中的映射地址和端口,...
在飞鸽的Java实现中,了解如何建立P2P连接,包括端口映射、NAT穿透等技术至关重要。 3. **套接字编程**:Java中的Socket编程用于在网络中实现两台计算机之间的通信。开发者需要熟悉ServerSocket和Socket类,以及...
在“WebRTC+Java实现多人视频通讯”的项目中,WebRTC主要负责前端的音视频采集、编码、传输和解码工作。用户可以在浏览器中直接参与视频通话,得益于WebRTC的API,开发者可以轻松获取用户的摄像头和麦克风权限,并...
NAT(网络地址转换)穿透技术就是为了在NAT环境下实现设备间的直接通信而设计的。本文将深入探讨NAT穿透的基本原理以及提供的源代码。 NAT是一种普遍应用于家庭和企业网络的技术,它允许一个或多个设备共享一个...
总的来说,Java中的JSTUN库提供了一种实现NAT穿透的方法,这对于开发分布式系统、P2P应用或者VoIP服务等需要跨NAT通信的应用非常有价值。开发者可以通过理解STUN协议和JSTUN库的工作原理,结合实际网络环境,来实现...