早就听说用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技术,内有详细的注释,完全可以自己看懂的
使用Java语言实现的Nat穿越的简单程序
该代码是计算机网络中经典的Nat穿越程序,使用java语言实现,需要三台电脑,两台路由器配合运行
为此,探讨 NAT 种类、应用及核心思想,及用 Java 网络包 java.net 实现 NAT 软交换的思路和方法,并根据网络存储系统安全问题,提出基于 NAT 的存储集群架构,分析其运行机制算法。模拟测试结果表明,基于 NAT 可在...
P2P内网穿透技术点,NAT网络探测。可以探测NAT网络类型,以及相关IP和端口。
JAVA穿越NAT,实现P2P的UDP通信。
就是非常有名的“UDP打洞技术”,UDP打洞技术依赖于由公共防火墙和cone NAT,允许适当的有计划的端对端应用程序通过NAT“打洞”,即使当双方的主机都处于NAT之后。这种技术在 RFC3027的5.1节[NAT PROT] 中进行了重点...
通过WebRTC实时通讯技术,配合后端java websocket实现多人视频。局域网内视频没问题,公网需要自行穿透NAT,项目整体为SpringBoot 外置Tomcat 启动
Stun4j 是 Java 程序实现 NAT 穿越的一种方案。是对 STUN 协议(RFC3489)的Java实现。
P2p之UDP穿透NAT的原理与实现代码,简单示例程序,希望大家喜欢。
UDP打洞实现了子网间的穿透功能,首先在一台拥有公网IP服务器上运行server,在不同的两个子网PC上运行client,输入服务器IP,即可进行打洞,实现不同子网的通信。
p2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdf
JAVA socket 端口转发,支持HTTP SOCKET。只是443 SSL加密。
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
用纯java代码写的点对点打洞技术,非常使用。希望对大家用帮助。
百度云盘分享 ... Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。 部分源代码摘录: ftpClient = new FtpClient(); //实例化FtpClient对象 String serverAddr=jtfServer.getText();...
Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。 部分源代码摘录: ftpClient = new FtpClient(); //实例化FtpClient对象 String serverAddr=jtfServer.getText(); //得到服务器地址 ...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
java-nat-xbox 针对求职者的 Nerdery 评估测试。 在本地运行 确保已安装 Java 和 Maven。 另外,安装 。 $ git clone https://github.com/wookets/java-nat-xbox.git $ cd java-nat-xbox $ mvn install $ foreman ...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...