P2P 打洞(Hole Punching)的步骤

TCP打洞流程:

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连接建立起来了.

UDP打洞流程:

1、客户端A登录服务器,服务器将客户端A的私网和公网终结点记录下来。

2、客户端B登陆服务器,服务器将客户端B的私网和公网终结点记录下来。

3、服务器将A的公网终结点发给客户端B。

4、客户端B向客户端A发一个数据包(此数据包作用:在客户端B的NAT上建立一个session,该session为B分配一个端口,即打了一个往A方向的洞口,以后如果有数据包从公网到达此端口,NAT将会把此数据包直接转发给客户端B)。但此时客户端A收不到此数据包,因为A端的NAT拦截了这个未曾谋面的数据包。

5、客户端B向服务器报告:已经向A方向打洞,此时服务器将B的公网终结点发给A,并命令客户端A往B方向发一个数据包(作用同第4步)。

6、客户端A发送一个数据包到客户端B的公网终结点上。此时,客户端B已经接收到A发送过来的这个数据包,至此打洞成功,以后A和B可以直接互相发送信息了!

Advertisements

About 寒江

程序人生。在代码的世界里泡了6年有余,渴望看看外面的世界!
此条目发表在通讯技术分类目录。将固定链接加入收藏夹。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s