NAT原理
网络地址转换(NAT,Network Address Translation)属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术。下面介绍两类不同方式实现的NAT: NAT(Network Address Translators):称为基本的NAT最后附一个JAVA的NAT实现,未验证
早就听说用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的内网地址才能成功。
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2302
- 用户1336
- 访客10968998
每日一句
Qingming Festival invites us to honor ancestors with quiet reflection and respect.
清明节邀请我们以静思与敬意祭奠祖先。
清明节邀请我们以静思与敬意祭奠祖先。
新会员