对等计算(Peer to Peer,简称p2p)可以简单的定义成通过直接交换来共享计算机资源和服务,而对等计算模型应用层形成的网络通常称为对等网络。在P2P网络环境中,成千上万台彼此连接的计算机都处于对等的地位,整个网络一般来说不依赖专用的集中服务器。
因为当前 IPV4地址的缺乏 ,nat、防火墙的中介设备和不对称寻址建立起来的 p2p通信机制造成了地址访问的问题。
在 internet最初体系结构中,每个节点都有全球唯一的 ip地址,能够直接通信。可是随着节点的增多, ip地址使用紧张,他们需要中介设备如 nat连在一起。 私有网络中的节点可以直接连接到相同私有网络中的其他节点,也可以连接到全局地址空间中拥有全球唯一 ip地址的节点。。然而 nat通常只允许临时的向外连接申请,对于向内的申请会拒绝。这就造成了在 natA内网中的节点 A连接 natB内网中的节点 B时连接申请报到 natB时就被阻止了。此时我们需要的就是穿越技术。。。
总体来说穿越技术是利用一个公共服务器中转,使节点 A、 B都连接到中转服务器 S之后,通过 S中转 A发送到 B的数据报或者是中转连接申请,,使 A、 B对于 natA和 natB来说都是向外申请。。。
1、 中转数据报: A、 B都先向外与服务器 S建立接连,然后通过 S中转 A、 B之间的数据报。。 2、 反向连接:当 A、 B都与 S建立了连接,并且只有一个节点在 nat之后(假设 A在 natA之后)。。当 B向 A申请连接时,申请背 natA拒绝。 B可以向 S提出申请要与 A建立连接,然后 S向 A发出指令,通知 A主动向 B申请建立连接。。 【 UDP打洞】 1、 A、 B在同一个 nat之后:
用户 A让 S做介绍人来与 B建立对话 (1) A向 S发送一个消息请求与 B建立连接 (2) S使用 B的公共终端( 155.99.25.11: 62005)和私有终端( 10.1.1.3)响应 A (3) 同时 S也想 B发送 A的公共终端( 155.99.25.11: 62000)和私有终端( 10.0.0.1),但是发送到公共终端的消息不一定能达到 B取决于 NAT是否支持“发夹”转化(回环转化) (4) 如果 nat支持发夹转化的话,应用程序就可以免除私有和共有终端都要试图连接的复杂性。。
2、 不同 NAT后面的节点
因为当前 IPV4地址的缺乏 ,nat、防火墙的中介设备和不对称寻址建立起来的 p2p通信机制造成了地址访问的问题。
在 internet最初体系结构中,每个节点都有全球唯一的 ip地址,能够直接通信。可是随着节点的增多, ip地址使用紧张,他们需要中介设备如 nat连在一起。 私有网络中的节点可以直接连接到相同私有网络中的其他节点,也可以连接到全局地址空间中拥有全球唯一 ip地址的节点。。然而 nat通常只允许临时的向外连接申请,对于向内的申请会拒绝。这就造成了在 natA内网中的节点 A连接 natB内网中的节点 B时连接申请报到 natB时就被阻止了。此时我们需要的就是穿越技术。。。
总体来说穿越技术是利用一个公共服务器中转,使节点 A、 B都连接到中转服务器 S之后,通过 S中转 A发送到 B的数据报或者是中转连接申请,,使 A、 B对于 natA和 natB来说都是向外申请。。。
1、 中转数据报: A、 B都先向外与服务器 S建立接连,然后通过 S中转 A、 B之间的数据报。。 2、 反向连接:当 A、 B都与 S建立了连接,并且只有一个节点在 nat之后(假设 A在 natA之后)。。当 B向 A申请连接时,申请背 natA拒绝。 B可以向 S提出申请要与 A建立连接,然后 S向 A发出指令,通知 A主动向 B申请建立连接。。 【 UDP打洞】 1、 A、 B在同一个 nat之后:
用户 A让 S做介绍人来与 B建立对话 (1) A向 S发送一个消息请求与 B建立连接 (2) S使用 B的公共终端( 155.99.25.11: 62005)和私有终端( 10.1.1.3)响应 A (3) 同时 S也想 B发送 A的公共终端( 155.99.25.11: 62000)和私有终端( 10.0.0.1),但是发送到公共终端的消息不一定能达到 B取决于 NAT是否支持“发夹”转化(回环转化) (4) 如果 nat支持发夹转化的话,应用程序就可以免除私有和共有终端都要试图连接的复杂性。。
2、 不同 NAT后面的节点
UDPServer.java
package org.renlr.test; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPServer { public static void main(String[] args) { try { DatagramSocket server = new DatagramSocket(2008); byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length); String sendMessage132 = ""; String sendMessage129 = ""; int port132 = 0; int port129 = 0; InetAddress address132 = null; InetAddress address129 = null; for (;;) { server.receive(packet); String receiveMessage = new String(packet.getData(), 0, packet.getLength()); System.out.println(receiveMessage); //接收到clientA if (receiveMessage.contains("132")) { port132 = packet.getPort(); address132 = packet.getAddress(); sendMessage132 = "host:" + address132.getHostAddress() + ",port:" + port132; } //接收到clientB if (receiveMessage.contains("129")) { port129 = packet.getPort(); address129 = packet.getAddress(); sendMessage129 = "host:" + address129.getHostAddress() + ",port:" + port129; } //两个都接收到后分别A、B址地交换互发 if (!sendMessage132.equals("") && !sendMessage129.equals("")) { send132(sendMessage129, port132, address132, server); send129(sendMessage132, port129, address129, server); sendMessage132 = ""; sendMessage129 = ""; } } } catch (Exception e) { e.printStackTrace(); } } private static void send129(String sendMessage132, int port132, InetAddress address132, DatagramSocket server) { try { byte[] sendBuf = sendMessage132.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, address132, port132); server.send(sendPacket); System.out.println("消息发送成功!"); } catch (Exception e) { e.printStackTrace(); } } private static void send132(String sendMessage129, int port129, InetAddress address129, DatagramSocket server) { try { byte[] sendBuf = sendMessage129.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, address129, port129); server.send(sendPacket); System.out.println("消息发送成功!"); } catch (Exception e) { e.printStackTrace(); } } }
UDPClientA.java
package org.renlr.test; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; public class UDPClientA { public static void main(String[] args) { try { // 向server发起请求 SocketAddress target = new InetSocketAddress("10.1.11.137", 2008); DatagramSocket client = new DatagramSocket(); String message = "I am UPDClinetA 192.168.85.132"; byte[] sendbuf = message.getBytes(); DatagramPacket pack = new DatagramPacket(sendbuf, sendbuf.length, target); client.send(pack); // 接收请求的回复,可能不是server回复的,有可能来自UPDClientB的请求内 receive(client); } catch (Exception e) { e.printStackTrace(); } } //接收请求内容 private static void receive(DatagramSocket client) { try { for (;;) { byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length); client.receive(packet); String receiveMessage = new String(packet.getData(), 0, packet.getLength()); System.out.println(receiveMessage); int port = packet.getPort(); InetAddress address = packet.getAddress(); String reportMessage = "tks"; //获取接收到请问内容后并取到地址与端口,然后用获取到地址与端口回复内容 sendMessaage(reportMessage, port, address, client); } } catch (Exception e) { e.printStackTrace(); } } //回复内容 private static void sendMessaage(String reportMessage, int port, InetAddress address, DatagramSocket client) { try { byte[] sendBuf = reportMessage.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, address, port); client.send(sendPacket); System.out.println("消息发送成功!"); } catch (Exception e) { e.printStackTrace(); } } }
UDPClientB.java
package org.renlr.test; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; public class UDPClientB { public static void main(String[] args) { try { //向server发起请求 SocketAddress target = new InetSocketAddress("10.1.11.137", 2008); DatagramSocket client = new DatagramSocket(); String message = "I am UDPClientB 192.168.85.129"; byte[] sendbuf = message.getBytes(); DatagramPacket pack = new DatagramPacket(sendbuf, sendbuf.length, target); client.send(pack); //接收server的回复内容 byte[] buf = new byte[1024]; DatagramPacket recpack = new DatagramPacket(buf, buf.length); client.receive(recpack); //处理server回复的内容,然后向内容中的地址与端口发起请求(打洞) String receiveMessage = new String(recpack.getData(), 0, recpack.getLength()); String[] params = receiveMessage.split(","); String host = params[0].substring(5); String port = params[1].substring(5); System.out.println(host + ":" + port); sendMessage(host, port, client); } catch (Exception e) { e.printStackTrace(); } } //向UPDClientA发起请求(在NAT上打孔) private static void sendMessage(String host, String port, DatagramSocket client) { try { SocketAddress target = new InetSocketAddress(host, Integer.parseInt(port)); for (;;) { String message = "I am master 192.168.85.129 count test"; byte[] sendbuf = message.getBytes(); DatagramPacket pack = new DatagramPacket(sendbuf, sendbuf.length, target); client.send(pack); //接收UDPClientA回复的内容 receive(client); } } catch (Exception e) { e.printStackTrace(); } } //收到UDPClientA的回复内容,穿透已完成 private static void receive(DatagramSocket client) { try { for (;;) { //将接收到的内容打印 byte[] buf = new byte[1024]; DatagramPacket recpack = new DatagramPacket(buf, buf.length); client.receive(recpack); String receiveMessage = new String(recpack.getData(), 0, recpack.getLength()); System.out.println(receiveMessage); //记得重新收地址与端口,然后在以新地址发送内容到UPDClientA,就这样互发就可以了。 int port = recpack.getPort(); InetAddress address = recpack.getAddress(); String reportMessage = "I am master 192.168.85.129 count test"; //发送消息 sendMessage(reportMessage, port, address, client); } } catch (Exception e) { e.printStackTrace(); } } private static void sendMessage(String reportMessage, int port, InetAddress address, DatagramSocket client) { try { byte[] sendBuf = reportMessage.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, address, port); client.send(sendPacket); System.out.println("send success"); } catch (Exception e) { e.printStackTrace(); } } }
收藏的用户(0) X
正在加载信息~
推荐阅读
win7纯净版制作EI Captian Clover引导安装U盘(续)
最新回复 (0)
站点信息
- 文章2300
- 用户1336
- 访客10861715
每日一句
True success inspires others to act.
真正的成功是激励他人行动。
真正的成功是激励他人行动。
语法错误: 意外的令牌“标识符”
全面理解Gradle - 定义Task
Motrix全能下载工具 (支持 BT / 磁力链 / 百度网盘)
谷歌Pixel正在开始起飞?
获取ElementUI Table排序后的数据
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is
亲测!虚拟机VirtualBox安装MAC OS 10.12图文教程
华为手机app闪退重启界面清空log日志问题
android ndk开发之asm/page.h: not found
手机屏幕碎了怎么备份操作?
免ROOT实现模拟点击任意位置
新手必看修改DSDT教程
thinkpad t470p装黑苹果系统10.13.2
新会员