udp p2p穿透网络类型(穿透流程)

Full Cone NAT:(完全锥形,知道公网ip和端口即可发送udp数据包)

   内网主机建立一个UDPsocket(LocalIP:LocalPort) 第一次使用这个socket给外部主机发送数据时NAT会给其分配一个公网(PublicIP:PublicPort),以后用这个socket向外面任何主机发送数据都将使用这对(PublicIP:PublicPort)。此外,任何外部主机只要知道这个(PublicIP:PublicPort)就可以发送数据给(PublicIP:PublicPort),内网的主机就能收到这个数据包

Restricted Cone NAT:(ip受限型,内网设备主动向此ip发送过数据,且外网设备知道此内网设备公网ip和端口,并使用此ip即可发送数据(任意端口))

   内网主机建立一个UDPsocket(LocalIP:LocalPort) 第一次使用这个socket给外部主机发送数据时NAT会给其分配一个公网(PublicIP:PublicPort),以后用这个socket向外面任何主机发送数据都将使用这对(PublicIP:PublicPort)。此外,如果任何外部主机想要发送数据给这个内网主机,只要知道这个(PublicIP:PublicPort)并且内网主机之前用这个socket曾向这个外部主机IP发送过数据。只要满足这两个条件,这个外部主机就可以用自己的(IP,任何端口)发送数据给(PublicIP:PublicPort),内网的主机就能收到这个数据包

Port Restricted Cone NAT:(端口受限型,内网设备主动向此ip发送过数据,且外网设备知道此内网设备公网ip和端口,并使用此ip即可发送数据(任意端口)

    内网主机建立一个UDPsocket(LocalIP:LocalPort) 第一次使用这个socket给外部主机发送数据时NAT会给其分配一个公网(PublicIP:PublicPort),以后用这个socket向外面任何主机发送数据都将使用这对(PublicIP:PublicPort)。此外,如果任何外部主机想要发送数据给这个内网主机,只要知道这个(PublicIP:PublicPort)并且内网主机之前用这个socket曾向这个外部主机(IP,Port)发送过数据。只要满足这两个条件,这个外部主机就可以用自己的(IP,Port)发送数据给(PublicIP:PublicPort),内网的主机就能收到这个数据包

Symmetric NAT:

    内网主机建立一个UDPsocket(LocalIP,LocalPort),当用这个socket第一次发数据给外部主机1时,NAT为其映射一个(PublicIP-1,Port-1),以后内网主机发送给外部主机1的所有数据都是用这个(PublicIP-1,Port-1),如果内网主机同时用这个socket给外部主机2发送数据,第一次发送时,NAT会为其分配一个(PublicIP-2,Port-2), 以后内网主机发送给外部主机2的所有数据都是用这个(PublicIP-2,Port-2).如果NAT有多于一个公网IP,则PublicIP-1和PublicIP-2可能不同,如果NAT只有一个公网IP,则Port-1和Port-2肯定不同,也就是说一定不能是PublicIP-1等于 PublicIP-2且Port-1等于Port-2。此外,如果任何外部主机想要发送数据给这个内网主机,那么它首先应该收到内网主机发给他的数据,然后才能往回发送,否则即使他知道内网主机的一个(PublicIP,Port)也不能发送数据给内网主机,这种NAT无法实现UDP-P2P通信。

 

NAT穿透UDP具体实现

本来是打算把我的java代码黏贴出来的,后来想了想,我写的只是其中一种实现方式,不同语言也有不同的实现方式,我就来说说实现的步骤,就不再写代码了。也挺简单的。

  1. 客户端建立一个UDP监听端口
  2. 客户端做一个心跳包向服务器发送数据包
  3. 服务器接收到心跳包后,储存客户端的ip、端口信息

当客户端要进行p2p通信的时候

  1. 发送方服务器查询接收方ip、端口
  2. 数据包定向ip、端口发送数据包
  3. 完成通信

注意 重点

到此,你以为结束了? 那就大错特错了。
到这里你会发现,接收方(以下统称A)可能拿不到数据包,这种情况出现在接收方在局域网内(需要穿透NAT)。
前面讲的,并不是仅仅获取到设备外网地址就可以成功穿透,还要注意NAT会把不认识的数据丢弃。
这是为什么?
NAT丢弃了你这个来源不明的包,根本没有分发给接收设备A。
为什么叫来源不明呢,这是因为首先A的UDP端口给服务器发数据包,A的NAT创建了一个session,这样A再接收到服务器的数据时,会查找这个映射(A<--->服务器),这个映射就储存在这个session里。但是发送方(B)向A的NAT发送数据(这是在B的NAT建立对A的映射),没有指向B的映射,所以数据包被A的NAT丢弃。
那怎么解决呢,其实让A也向B发一个数据包就好了,这样A的NAT会建立一个对B的session,这样再收到B的数据NAT就可以查找到对应的映射了。

之前提到的NAPT对UDP的session映射,源地址相同,源端口相同,目标地址不同,对于不同的NAPT,session可能不同。这条规则是依据不同的NAT的。Symmetric NAPT会导致session不同,Cone NAPT则是相同的。对于p2p只要一方使用的是Symmetric NAPT就会导致无法穿透。具体可自行百度。

此处我将NAT分为两类,ConeNAT和SymmetricNAT。

A.   ConeNAT借助服务器采用P2P方式

设定A和B为不同内网设备,S为公网服务器,P2P实现过程如下:

1)   A,B定时向S发送心跳包,间隔为50秒,S取得A和B的网络信息A(IP:PORT),B(IP,PORT)

2)   A连接S,请求进行p2p连接(命令B向A公网地址发送测试数据包,同时返回B公网地址供A发送测试数据包)

3)   当A端明确接收到B端响应数据,完成穿透流程

4)   A,B通信建立,保持50秒内有相互的UDP信息交流,即需要建立A和B之间的心跳

B.   SymmetricNAT采用服务器中转方式

设定A和B为内网设备,S为中转服务器,中转实现方式如下

1)   A,B定时向S发送心跳包,间隔为50秒,S取得A和B的网络信息A(IP:PORT),B(IP,PORT)

2)   A发送UDP信息给S,S发送到B(IP,PORT)

3)   B发送UDP信息给S,S发送到A(IP:PORT)

4)   通信成功


猜你喜欢

转载自blog.csdn.net/qq_27688259/article/details/79424518