`
kayo
  • 浏览: 549140 次
  • 性别: Icon_minigender_1
  • 来自: 安徽
社区版块
存档分类
最新评论
阅读更多
早就听说用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的内网地址才能成功。
 
分享到:
评论
2 楼 wzpwork 2011-03-21  
如果没理解错误的话应该是下面这样的:

这个Server.java应该要在公网的服务器上运行,

UDPClient.java中的这行代码要适当修改下:
new UDPClient("www.javadoc.cn", 2008, -1).start(); 

将这行代码改为
new UDPClient(运行Sserver.java公网服务器IP, 2008, -1).start();

这样程序才能运行。

这里弱弱的问一下楼主,在这个NAT中,关键的是哪几句代码,帮忙注释一下,好让兄弟们更深入的了解。

谢谢!
1 楼 mj4678 2009-10-23  
楼主,为什么我用你的测试一直么通过呢。。。。能否给个完整的测试程序参考下。。
178513351@qq.com

相关推荐

    Java实现UDP穿透NAT技术

    用Java实现的UDP穿透NAT技术,内有详细的注释,完全可以自己看懂的

    Java NAT穿越

    使用Java语言实现的Nat穿越的简单程序

    Nat.zip_NAT java_java nat

    该代码是计算机网络中经典的Nat穿越程序,使用java语言实现,需要三台电脑,两台路由器配合运行

    基于 Java 的 NAT 软交换代理及存储集群系统研究

    为此,探讨 NAT 种类、应用及核心思想,及用 Java 网络包 java.net 实现 NAT 软交换的思路和方法,并根据网络存储系统安全问题,提出基于 NAT 的存储集群架构,分析其运行机制算法。模拟测试结果表明,基于 NAT 可在...

    NAT探测 使用stun协议 java和python版本

    P2P内网穿透技术点,NAT网络探测。可以探测NAT网络类型,以及相关IP和端口。

    JAVA穿越NAT

    JAVA穿越NAT,实现P2P的UDP通信。

    udp.zip_ICE NAT_UDP nat java_nat_udp打洞_最新防火墙

    就是非常有名的“UDP打洞技术”,UDP打洞技术依赖于由公共防火墙和cone NAT,允许适当的有计划的端对端应用程序通过NAT“打洞”,即使当双方的主机都处于NAT之后。这种技术在 RFC3027的5.1节[NAT PROT] 中进行了重点...

    WebRTC+java实现多人视频通讯

    通过WebRTC实时通讯技术,配合后端java websocket实现多人视频。局域网内视频没问题,公网需要自行穿透NAT,项目整体为SpringBoot 外置Tomcat 启动

    STUN协议的java实现,stun4j

    Stun4j 是 Java 程序实现 NAT 穿越的一种方案。是对 STUN 协议(RFC3489)的Java实现。

    P2p之UDP穿透NAT的原理与实现代码

    P2p之UDP穿透NAT的原理与实现代码,简单示例程序,希望大家喜欢。

    java udp p2p nat 等打洞技术实现通信,已测试成功

    UDP打洞实现了子网间的穿透功能,首先在一台拥有公网IP服务器上运行server,在不同的两个子网PC上运行client,输入服务器IP,即可进行打洞,实现不同子网的通信。

    p2p网络穿越中nat类型检测的原理与实现.pdf

    p2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdfp2p网络穿越中nat类型检测的原理与实现.pdf

    JAVA端口转发工具源码

    JAVA socket 端口转发,支持HTTP SOCKET。只是443 SSL加密。

    java开源包4

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java打洞代码

    用纯java代码写的点对点打洞技术,非常使用。希望对大家用帮助。

    JAVA上百实例源码以及开源项目

    百度云盘分享 ... Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText();...

    JAVA上百实例源码以及开源项目源代码

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器地址  ...

    java开源包3

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java-nat-xbox:对您的开发能力的基于 Java 的评估测试

    java-nat-xbox 针对求职者的 Nerdery 评估测试。 在本地运行 确保已安装 Java 和 Maven。 另外,安装 。 $ git clone https://github.com/wookets/java-nat-xbox.git $ cd java-nat-xbox $ mvn install $ foreman ...

    java开源包101

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

Global site tag (gtag.js) - Google Analytics