P2P 就是端到端
我发一条微信给你,这不是 P2P。因为消息并不是直接从我手机发送到你的手机,而是从我手机先发送到微信的服务器,服务器再转发到你的手机上(当然,转发给你之前,还会把数据存到服务器),像下边这样:
P2P 是这样:
P2P 技术要解决的问题
目前使用的终端设备(如手机),绝大部分都仅仅拥有特定网络下的内网 IP,而处在不同内网环境中的设备并不能够使用内网 IP 直接进行通信。如何通过一定的手段让这两个处在不同内网环境的设备进行直接通信呢?
P2P 的知识点
我们的终端设备(比如手机),一定是存在于某个内网环境下边的,当设备与内网之外的其他设备进行通信时,需要将内网 IP 转换为一个可以被全球任意设备访问到的公网 IP,这种技术叫做 NAT,全称是 Network Address Translation,即网络地址转换。
根据转换方式的不同,出现了不同的 NAT,理论上有基本 NAT,也有一对多 NAT,但是现实中基本都是一对多 NAT,根据内网设备与外网进行通信时不同的映射规则,又分为以下几种类型:
类型 | 阐述 |
---|---|
锥型 NAT(Full-cone NAT) | 内网 ip1:port1 会映射到公网 ip2:port2,ip1:port1 发往外网的包都将通过 ip2:port2 发出;外部任何 ip3:port3 都可以通过发送数据包给 ip2:port2 从而与 ip1:port1 进行通信。 |
(地址)限制型锥型 NAT((Address)-restricted-cone NAT) | 内网 ip1:port1 会映射到 ip2:port2,ip1:port1 发往外网的包都将通过 ip2:port2 发出;外部只有收到过 ip2:port2 数据包的 ip3 才可以发送数据包给 ip2:port2 从而与 ip1:port1 进行通信。 |
端口限制型锥型 NAT(Port-restricted cone NAT) | 内网 ip1:port1 会映射到 ip2:port2,ip1:port1 任何发往外网的包都将通过 ip2:port2 发出;外部只有收到过 ip2:port2 数据包的 ip3:port3 才可以发送数据包给 ip2:port2 从而与 ip1:port1 进行通信。 |
对称性 NAT(Symmetric NAT) | 内网 ip1:port1 任何一个发往外网 ip3:port3 的请求,都将使用独有的公网 ip2:port2;外部只有收到过 ip1:port1 数据包的服务才能返回数据。 |
总的来说,我们程序发出的包有源地址和源端口,经过 NAT 之后,映射出的公网地址和端口是否会随着目的地址和目的端口的变化而变化,决定了它是锥型还是对称型。这句话有点拗口,但我觉得说的很清楚。同时,只有锥型 NAT 才能进行 P2P,原因是由 P2P 连接的建立过程决定的。
P2P 连接建立过程
P2P 连接的建立首先需要一个拥有公网 IP 的中间服务器 S,两个结点 P1 和 P2。
- 结点 P1 和 P2 分别发送数据包给 S,数据包在经过 NAT 时,ip 和 port 进行转换,ip 转换为公网 ip,port 是否转换需要看 NAT 的具体实现。S 拿到转换后的 P1 和 P2 的地址。
- S 将 P1 的地址发给 P2,将 P2 的地址发给 P1。这里的地址都是 NAT 地址。
- P1 收到 P2 地址后,尝试建立连接,首先发送消息包给 P2(其实是 P2 的 NAT),P2 也同样这样做,在两个结点都收到对方的消息包之后,就可以进行通信了。这个过程也叫做打洞。
之所以需要有打洞这个过程,是因为,NAT 会丢弃自己不认识的地址包,让 NAT 认识它的方法,就是发出一个到这个地址的数据包。比如让 A 认识 B,那就让 A 发一个数据包给 B,不然,B 发给 A 的数据包就会被丢弃。所以打洞的过程不是为了收到对方的数据包,而是为了发送数据包给对方,从而认识对方。这样,之后的通信就可以正常进行了。
刚才之所以说只有锥型 NAT 才可以进行 P2P,原因在第三步可以看出来。结点进行打洞的地址,是通过服务器拿到的,而这个地址在对称型 NAT 的情况下,并不是一定的,可能会随时发生变化。也就是说,P1 与服务器通信使用的 NAT 地址和 P2 与 P1 通信使用的 NAT 地址是不同的(一般情况都是端口不同)。甚至 P1 与服务器通信使用的 NAT 地址都在不断的发生变化。这样让我们没办法拿到隐藏在 NAT 后边内网设备的 NAT 入口,也就没办法进行 P2P 通信了。
P2P 也用到了一个服务器,跟微信一样。但是不同的是,P2P 中的服务器只作为结点地址的中转站,而微信的服务器是数据的聚宝盆。P2P 让我们的数据仅通过 P2P 连接发送,而不经过任何第三方的服务器。