当前位置: 代码迷 >> 综合 >> P2P通信流程
  详细解决方案

P2P通信流程

热度:96   发布时间:2024-02-08 01:34:56.0

假设:一台公网服务器S,一台内网主机A及其路由器NAT-A,另一台内网主机B及其路由器NAT-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连接建立起来了。

 

假设我们有两台处于不同内网的两台机器A和B和一台众所周知外网IP的服务器S,而机器A中运行着通讯的服务端程序B运行着通讯的客户端程序,那么

1、A连接S,S记录A的外网IP与通讯的端口
2、B连接S
3、S将A与此通讯的端口号返回给A
4、S将A与此连接的IP与端口号返回给B
5、A在程序中将服务绑定并侦听在从S返回的端口
6、B使用从S返回的IP与端口连接A

 

手机跟PC机TCP打洞,PC机充当服务端,手机充当客户端,公网服务器Server充当桥梁。

备注:在建立PC和手机直连之前,Server充当服务器,P2P建立后,可以关闭撤掉

注意:由于要在相同的网络终端上绑定到不同的Socket上,所以必须将Socket选项设置为 SO_REUSEADDR 属性(即允许重用)

1、Server启动2个Socket网络监听,一个主连接Socket,一个协助打洞Socket,PC和手机分别与主连接Socket建立联系。

2、手机连接Server的协助打洞Socket,并发送协助连接申请,并启动监听接受数据。

3、Server的协助打洞Socket收到手机的申请,通过已存在的主连接Socket通知PC,并将手机的公网IP和端口告诉PC。

4、PC收到Server的连接通知后,先与协助打洞Socket连接,发送一次随意数据立即断开,让Server获取到PC的外网IP和端口。

5、PC尝试连接手机的公网IP和端口,根据不同的路由器会有不同的结果,大多数会connect失败,但是会记住此次连接的源地址和端口号,为接下来真正的连接做好了准备,这就是所谓的打洞,即PC向手机打了一个洞,下次手机就能直接连接到PC刚才使用的端口号。

6、PC打洞的同时,在相同的端口上启动侦听,并给主连接Socket发送“我已准备好了”,Server在收到后,把PC的公网IP和端口告诉手机。

7、手机收到后,就可以直连到PC。

 

1. PC连接Server,Server保存PC的外网IP和Port,并且返回外网IP和Port给PC

2.手机连接Server,Server返回PC的外网IP和Port给手机

3.PC在程序中将Socket服务绑定并侦听从Server返回的端口

4.手机使用从Server返回的IP和Port连接A

 

 

 

 

 

  相关解决方案