Internet的迅速发展以及IPv4 地址数量的限制使得网络地址翻译(NAT,Network Address Trans2lation)设备得到广泛应用。NAT设备允许处于同一NAT后的多台主机共享一个公网(本文将处于同一NAT后的网络称为私网,处于NAT前的网络称为公网) IP 地址。一个私网IP 地址通过NAT设备与公网的其他主机通信。公网和私网IP地址域,如下图所示:

INTERNET

202.103.142.29

NAT-A

192.168.0.1

电脑A-01

192.168.0.2

电脑A-02

192.168.0.3

电脑A-01

192.168.1.12

电脑A-02

192.168.1.13

Server ( Web、FTP、POP3、SMTP、IIS、Database … )

129.208.12.38

221.10.145.84

NAT-B

192.168.1.1

广域网与私网示意图

一般来说都是由私网内主机(例如上图中“电脑A-01”)主动发起连接,数据包经过NAT地址转换后送给公网上的服务器(例如上图中的“Server”),连接建立以后可双向传送数据,NAT设备允许私网内主机主动向公网内主机发送数据,但却禁止反方向的主动传递,但在一些特殊的场合需要不同私网内的主机进行互联(例如P2P软件、网络会议、视频传输等),TCP穿越NAT的问题必须解决。网上关于UDP穿越NAT的文章很多,而且还有配套源代码,但是我个人认为UDP数据虽然速度快,但是没有保障,而且NAT为UDP准备的临时端口号有生命周期的限制,使用起来不够方便,在需要保证传输质量的应用上TCP连接还是首选(例如:文件传输)。

网上也有不少关于TCP穿越NAT(即TCP打洞)的介绍文章,但不幸我还没找到相关的源代码可以参考,我利用空余时间写了一个可以实现TCP穿越NAT,让不同的私网内主机建立直接的TCP通信的源代码。

这里需要介绍一下NAT的类型:

NAT设备的类型对于TCP穿越NAT,有着十分重要的影响,根据端口映射方式,NAT可分为如下4类,前3种NAT类型可统称为cone类型。

(1)全克隆( Full Cone) : NAT把所有来自相同内部IP地址和端口的请求映射到相同的外部IP地址和端口。任何一个外部主机均可通过该映射发送IP包到该内部主机。

(2)限制性克隆(Restricted Cone) : NAT把所有来自相同内部IP地址和端口的请求映射到相同的外部IP地址和端口。但是,只有当内部主机先给IP地址为X的外部主机发送IP包,该外部主机才能向该内部主机发送IP包。

(3)端口限制性克隆( Port Restricted Cone) :端口限制性克隆与限制性克隆类似,只是多了端口号的限制,即只有内部主机先向IP地址为X,端口号为P的外部主机发送1个IP包,该外部主机才能够把源端口号为P的IP包发送给该内部主机。

(4)对称式NAT ( Symmetric NAT) :这种类型的NAT与上述3种类型的不同,在于当同一内部主机使用相同的端口与不同地址的外部主机进行通信时, NAT对该内部主机的映射会有所不同。对称式NAT不保证所有会话中的私有地址和公开IP之间绑定的一致性。相反,它为每个新的会话分配一个新的端口号。

我们先假设一下:有一个服务器S在公网上有一个IP,两个私网分别由NAT-A和NAT-B连接到公网,NAT-A后面有一台客户端A,NAT-B后面有一台客户端B,现在,我们需要借助S将A和B建立直接的TCP连接,即由B向A打一个洞,让A可以沿这个洞直接连接到B主机,就好像NAT-B不存在一样。

实现过程如下(请参照源代码):

1、  S启动两个网络侦听,一个叫【主连接】侦听,一个叫【协助打洞】的侦听。

2、  A和B分别与S的【主连接】保持联系。

3、  当A需要和B建立直接的TCP连接时,首先连接S的【协助打洞】端口,并发送协助连接申请。同时在该端口号上启动侦听。注意由于要在相同的网络终端上绑定到不同的套接字上,所以必须为这些套接字设置 SO_REUSEADDR 属性(即允许重用),否则侦听会失败。

4、  S的【协助打洞】连接收到A的申请后通过【主连接】通知B,并将A经过NAT-A转换后的公网IP地址和端口等信息告诉B。

5、  B收到S的连接通知后首先与S的【协助打洞】端口连接,随便发送一些数据后立即断开,这样做的目的是让S能知道B经过NAT-B转换后的公网IP和端口号。

6、  B尝试与A的经过NAT-A转换后的公网IP地址和端口进行connect,根据不同的路由器会有不同的结果,有些路由器在这个操作就能建立连接(例如我用的TPLink R402),大多数路由器对于不请自到的SYN请求包直接丢弃而导致connect失败,但NAT-A会纪录此次连接的源地址和端口号,为接下来真正的连接做好了准备,这就是所谓的打洞,即B向A打了一个洞,下次A就能直接连接到B刚才使用的端口号了。

7、  客户端B打洞的同时在相同的端口上启动侦听。B在一切准备就绪以后通过与S的【主连接】回复消息“我已经准备好”,S在收到以后将B经过NAT-B转换后的公网IP和端口号告诉给A。

8、  A收到S回复的B的公网IP和端口号等信息以后,开始连接到B公网IP和端口号,由于在步骤6中B曾经尝试连接过A的公网IP地址和端口,NAT-A纪录了此次连接的信息,所以当A主动连接B时,NAT-B会认为是合法的SYN数据,并允许通过,从而直接的TCP连接建立起来了。

TCP实现P2P通信相关推荐

  1. TCP实现P2P通信、TCP穿越NAT的方法、TCP打洞

    原文地址:http://www.vckbase.com/document/viewdoc/?id=1773 这个标题用了两个顿号三个名称,其实说得是同一个东西,只是网上有不同的说法罢了,另外好像还有人 ...

  2. ESFramework Demo -- P2P通信Demo(附源码)

    现在我们将在ESFramework Demo -- 文件传送Demo 的基础上,使用ESPlus提供的第四个武器,为其增加P2P通信的功能.在阅读本文之前,请务必先掌握ESFramework 开发手册 ...

  3. 穿越NAT的p2p通信方法研究

    穿越NAT的p2p通信方法研究 日期:2008-12-08 来源:P2P网  作者:未知 字体:大 中 小 <script src="http://www.ppcn.net/ads/b ...

  4. Android P2P 通信方案探索

    最近研究起了P2P网络,p2p网络其它很早就有了,但是用到的地方不多,以前最多用来p2p种子下载音乐视频这类的应用,对它的原理也一知半解,以p2p下载视频为例,大概原理:服务器里并不保存视频资源,只是 ...

  5. P2P通信中的NAT/FW穿越

    摘要:P2P(Peer-to-Peer)通信的发展极其迅速,形成了很大的影响.和传统通信一样,P2P通信同样受到NAT/FW穿越问题的制约,因此解决好其相关的NAT/FW穿越问题非常重要.和传统通信相 ...

  6. 内网穿透实现P2P通信

    P2P 通信最大的障碍就是 NAT(网络地址转换),NAT 使得局域网内的设备可以与公网进行通讯,但是不同 NAT 下的设备之间通讯将会变得很困难.UDP 打洞就是用来使得设备间绕过 NAT 进行通讯 ...

  7. P2P通信基本原理与实现

    本文转载自: https://www.pppan.net/blog/detail/2017-12-16-p2p-over-middle-box 如有侵权,通知删除 P2P通信基本原理与实现 #P2P ...

  8. 网络协议漫游-HTTP | TCP/IP | P2P

    网络协议漫游-HTTP | TCP/IP | P2P HTTP协议入水 由三部分组成 状态行(请求行 | 响应行).首部.主体 状态行 首部 主体 HTTP 无状态协议详解 HTTP请求与响应 HTT ...

  9. P2P通信原理与实现(C++),NAT,网络穿透原理

    1.简介 当今互联网到处存在着一些中间件(MIddleBoxes),如NAT和防火墙,导致两个(不在同一内网)中的客户端无法直接通信.这些问题即便是到了IPV6时代也会存在,因为即使不需要NAT,但还 ...

最新文章

  1. OpenCV中CvArr* 的含义~
  2. 再谈fedora下的音乐和视频播放器的安装
  3. shell:syntax error:unexpected end of file/Starting proxy www-balancer: cannot bind socket--转载
  4. 淘宝网消费者年维权成功金额达1.69亿
  5. 2010考研全程学习规划简案【推荐】
  6. Java设计链表(不带头结点的单链表)
  7. 实现机器学习的循序渐进指南V——支持向量机
  8. MediaStreamTrackAudioSourceNode
  9. python——argsort函数
  10. kali的sqlmap安装
  11. linux环境使用c语言获取当前目录下有哪些文件,并打印它们的名字
  12. C语言模拟实现memcmp函数
  13. Excel报:文件已损坏无法打开错误问题解决
  14. uni-app关于uni.navigateTo的坑以及解决方案
  15. Linux Mint 18.2 安装与调整
  16. 给拯救者Y7000换个固态
  17. 初学ARM的个人心得
  18. 工厂模式——简单工厂模式、工厂方法模式和抽象工厂模式
  19. Linux 下编译自己的 OpenJDK7 包括JVM和JDK API
  20. 「直播回放」数仓如何落地

热门文章

  1. 从阿里高层辞职想到的
  2. 后缀自动机 (WJMZBMR讲稿的整理和注释)
  3. 5款软件压力测试工具分享
  4. ckeditor粘贴word文档图片的方案
  5. OpenCV——图像腐蚀
  6. html画布创建黑白象棋棋盘,HTML5学习与加固——canvas绘图象棋盘
  7. cocos creator2.4.4益智教育游戏源码《顶级食物链》源码H5+安卓+IOS三端源码
  8. OSX-Mac平台画板工具推荐-SktechBook
  9. 网络富豪 百度李彦宏全球第二
  10. php 五子棋对战,五林大会五子棋