p2p 打洞技术
根据通信双方所处网络环境不同,点对点通信可以划分成以下三类:
i> 公网:公网
ii>公网:内网
iii>内网:内网
前两种容易实现,我们这里主要讨论第三种。
这其中会涉及到NAT和NAPT的概念,请大家预先浏览一下:https://en.wikipedia.org/wiki/Network_address_translation(NAT)。NAT目前主要依托于路由器实现:
其中cone NAT中分三种,它们在内外网ip:port的映射机制也不同:
内网 ip_i:port_i <--> NAT ip_o:port_o (相同的 内网 ip_i:port_i 无论访问哪个外部网址,在映射的生命周期内 NAT ip_o:port_o 不会改变)
Full: 所有发送到ip_o:port_o的消息都会转发到ip_i:port_i上
Restricted: 只有ip_i:port_i 访问过的 addr(不限制端口{host:any}),其发送到ip_o:port_o的消息才会转发到ip_i:port_i上
Port Restricted:只有ip_i:port_i 访问过的 addr(限制端口{host: port_o}),其发送到ip_o:port_o的消息才会转发到ip_i:port_i上
Sysmmetric NAT则与以上都不同:
每次内网ip_i:port_i 访问不同的addr(host不同或port不同,都算是不同地址)时,会映射到不同的 NAT ip_o:port_o
以上四种 NAPT 类型在p2p情况下(A and B)有 10 种组合方式,根据发起方不同可以扩展到 16种情况,这十六种情况中并不是每一种情况都能打洞成功的。现有网上的资料显示,内网:内网 情况下打洞都是需要打洞服务器进行引导的,打洞又分UDP和TCP两种情况,我们大致说一下打洞的流程:
假设 A 和 B 双方都是 cone 模式, 在 服务器 S 的引导下进行 TCP打洞
(1)A 和 B 向 S 通过 UDP 发送消息(S 可以从 UDP 消息提取出其公网 IP)
(2)A (ip_a_i, port_a_i) 向 S 建立 TCP 链接,发送与B 通讯的请求,同时 监听 (ip_a_i, port_a_i)
(3)S 提取出 A tcp 链接的公网地址(ip_a_o, port_a_o), 通过UDP协议向 B 发送(ip_a_o, port_a_o)
(4)B 向 (ip_a_o, port_a_o)发起TCP链接请求,如果失败则执行第5步,如果成功则到此为止
(5)B 保持内网地址(ip_b_i,port_b_i)不变向 S 发起TCP链接请求,通知其已经向A发送了链接请求,并监听(ip_b_i,port_b_i)
(6)S 提取出 B的tcp链接公网(ip_b_o, port_b_o), 通过UDP 将(ip_b_o, port_b_o)发送给A
(7) A 通过(ip_a_i, port_a_i)向 B发起链接请求
其中Sysmmetric :Sysmmetric 和 Sysmmetric:Port Restricted 这两种组合是没办法打洞的:
我们假设A是 Sysmmetric \ B 是 Port Restricted
《1》当 A 向 S 发起tcp链接的时候 假设形成 NAT 映射(192.168.1.4:8080 <--> 61.22.37.16:33956)
《2》S 将 61.22.37.16:33956 转发给 B ,B 向该地址发起链接请求
《3》B的路由器的路由表中会添加 61.22.37.16:33956 这个地址,如果A再次通过该地址来向B发起通信就可以完成通信
然而,当A向B发起访问的时候会形成一个新的 NAT 映射关系,产生一个新的公网地址,所以B不会接受其访问。反之如果A是 Port Restricted\ B是 Sysmmetric 也无法完成打洞,大家可以自己思考一下为什么。
p2p 打洞技术的更多相关文章
- [p2p]UDP用打洞技术穿透NAT的原理与实现
首先先介绍一些基本概念: NAT(Network Address Translators),网络地址转换:网络地址转换是在IP地址日益缺乏的情况下产生的, ...
- P2P技术基础: 关于TCP打洞技术
4 关于TCP打洞技术 建立穿越NAT设备的p2p的 TCP 连接只比UDP复杂一点点,TCP协议的“打洞”从协议层来看是与UDP的“打洞”过程非常相似的.尽管如此,基于TCP协议的打洞至今为止还没有 ...
- UDP 构建p2p打洞过程的实现原理(持续更新)
UDP 构建p2p打洞过程的实现原理(持续更新) 发表于7个月前(2015-01-19 10:55) 阅读(433) | 评论(0) 8人收藏此文章, 我要收藏 赞0 8月22日珠海 OSC 源创 ...
- TCP打洞技术
//转http://iamgyg.blog.163.com/blog/static/3822325720118202419740/ 建立穿越NAT设备的p2p的TCP连接仅仅比UDP复杂一点点,TCP ...
- p2p 打洞专场(转)
就像1000个人眼中有1000个哈姆雷特一样,每个人眼中的区块链也是不一样的!作为技术人员眼中的区块链就是将各种技术的融合,包括密码学,p2p网络,分布式共识机制以及博弈论等.我们今天就来讨论一下区块 ...
- NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等
这是一篇介绍NAT技术要点的精华文章,来自华3通信官方资料库,文中对NAT技术原理的介绍很全面也很权威,对网络应用的应用层开发人员而言有很高的参考价值. 学习交流 移动端即时通讯学习交流: 21589 ...
- 低延时的P2P HLS直播技术实践
本文根据4月21日OSC源创会·武汉站的现场分享为蓝本,重新整理.以下是演讲内容: 近几年,随着直播.短视频等视频领域对带宽要求的提升以及CDN行业竞争的加剧,很多CDN公司开始往P2P-CDN方向发 ...
- 【Todo】UDP P2P打洞原理
参考以下两篇文章: https://my.oschina.net/ososchina/blog/369206 http://m.blog.csdn.net/article/details?id=666 ...
- P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解
1.内容概述 P2P即点对点通信,或称为对等联网,与传统的服务器客户端模式(如下图"P2P结构模型"所示)有着明显的区别,在即时通讯方案中应用广泛(比如IM应用中的实时音视频通信. ...
随机推荐
- C#中级-从零打造基于Socket在线升级模块
一.前言 前段时间一直在折腾基于Socket的产品在线升级模块.之前我曾写过基于.Net Remoting的.基于WCF的在线升级功能,由于并发量较小及当时代码经验的不足一直没有实际应用. ...
- HDU 1043 Eight (BFS·八数码·康托展开)
题意 输出八数码问题从给定状态到12345678x的路径 用康托展开将排列相应为整数 即这个排列在全部排列中的字典序 然后就是基础的BFS了 #include <bits/stdc++.h ...
- 【Linux探索之旅】第二部分第五课:用户和权限,有权就任性
内容简单介绍 .第二部分第五课:用户和权限,有权就任性 2.第二部分第六课预告:Nano,刚開始学习的人的文本编辑器 用户和权限.有权就任性 今天的标题也挺任性的啊,虽说小编是一个非常本分的人(真的吗 ...
- dubbo2.5.6从下载到编译成功并且部署成功过程
本文基于dubbo2.5.6版本 原文链接:http://www.cnblogs.com/zhuwenjoyce/ 1,下载dubbo 首先从 github 下载源代码并阅读 readme ...
- [.Net跨平台]部署DTCMS到Jexus遇到的问题及解决思路--验证码
上一篇博客我们已经基本完成了部署工作,目前发现了验证码出现500错误,分析其代码,我们可以看到验证码使用的是System.Drawing命名空间下的类库, GDI+ 位图,这个在肯定是平台相关的,所以 ...
- 肖秀荣8套卷2018pdf下载|2018肖秀荣冲刺8套卷pdf下载电子版
肖秀荣8套卷2018pdf下载|2018肖秀荣冲刺8套卷pdf下载电子版 下载链接: https://u253469.ctfile.com/fs/253469-229815828
- HTTP服务及状态码
第一章 HTTP 1.1 HTTP协议的概念 HTTP协议,全称HyperText Transfer Protocol,中文名为超文本传输协议,是互联网上常用的通信协议之一,它有很多的应用.但是流行的 ...
- 安装puppet
安装puppet服务 先安装ruby语言包.ruby标准库.ruby shadow库 yum install -y ruby ruby-libs ruby-shadow 2.需要添加EPRL库,来支持 ...
- android 串口开发第二篇:利用jni实现android和串口通信
一:串口通信简介 由于串口开发涉及到jni,所以开发环境需要支持ndk开发,如果未配置ndk配置的朋友,或者对jni不熟悉的朋友,请查看上一篇文章,android 串口开发第一篇:搭建ndk开发环境以 ...
- python模拟shell执行脚本
工作时候需要模拟shell来执行任务,借助包paramkio import paramiko class ShellExec(object): host = '127.0.0.1' port = 36 ...