作者|张裕鹏,单位:中国移动智慧家庭运营中心
Labs 导读
随着视频物联网的发展,IPC(IPCamera,网络摄像头)已经在家庭安防场景广泛应用。中国移动移动看家业务提供了以视频为基础的场景化安防服务,支持接入IPC、门锁、猫眼等泛安防智能硬件,用户通过使用和家亲APP可以实现远程看护、设备对讲、监控视频回放等功能。为了实现以上功能,IPC等设备需使用流媒体传输协议发送摄像头采集到的音视频媒体流,而APP则通过流媒体传输协议获取媒体流。
目前市面上常见的流媒体传输协议有:RTMP、WebRTC、QUIC、P2P、SRT等。移动看家使用的流媒体传输协议主要有P2P和SRT。关于这两个协议,笔者准备用两篇文章进行介绍,本文先介绍P2P协议。
1什么是P2P?
简单来说P2P就是设备之间不通过中间服务器转发,直接进行点对点的通信的方式。
那么非P2P是如何通信的呢?我们以微信通信为例,简单介绍一下:
图1
从图1中我们可以看到,小明通过微信给小红发了一条消息,其消息的真实流经路径是:小明->腾讯服务器->小红。
那么问题就来了,为什么消息要先经过腾讯服务器,而不能是直接:小明->小红?
答:小明的手机在网络上大概率是无法直接找到小红的手机。
如何理解这句话?请看图2
图2
我们都知道,在网络世界中,是通过IP地址来唯一确定某一台设备的,但是由于IPv4地址数量的有限性,导致很多设备其实是无法获取到唯一的IP地址(公网地址),而是使用NAT(网络地址转换)技术获取一个内网地址,多个内网地址共用一个公网地址实现上网。家庭中常见的内网地址有:192.168.X.X 。
公网地址唯一,而内网地址不唯一,所以如果只是知道一个设备的内网IP地址是无法找到对应设备的(除非是刚好处在同一个内网环境中),这也就是为什么小明的手机在网络上大概率是找不到小红手机的原因。
而腾讯服务器由于有自己的公网地址,因此小明和小红都可以通过这个公网地址都可以找到腾讯服务器,然后通过腾讯服务器这个中介,小明和小红就可以通信了。
从图2中我们也可以发现,小明的手机连接的路由器A的WAN口的IP地址(公网地址)是:36.23.223.162;小红的手机连接路由器B的WAN口的IP地址(公网地址)是:183.129.184.211。要是小明能知道自己的公网IP地址,并告诉小红(反过来也是一样),也就能跳过腾讯服务器直接与对方相连。这其实也就是 P2P 的技术原理。
2为什么要使用P2P?
使用P2P的好处有很多,从不同的角度出发可以得到不同的答案。如果站在设备厂商的角度来看,如果他们的设备之间能实现P2P,那就可以减少中转服务器的流量费用,特别是当数据量大的时候,P2P省流量的优势就更加明显,从而降低运营成本。从技术方面来看,P2P 直接跳过服务器中转,因此只要能连接成功,其传输速度从理论上来说会更快。
图3
3如何实现P2P?
从图2的描述中我们知道,如果设备能知道自己本身的公网IP地址和端口,并告诉对方,就能实现P2P通信。所以要实现P2P通信,就要解决以下两个问题:
- 如何获取自身的公网IP地址和端口
- 如何将获取到的公网IP地址和端口告诉对端
3.1 NAT原理
关于如何获取自身的IP公网地址和端口,我们可以参考浏览器访问百度搜索引擎的流程,如下图:
图4
图中路由器下面连接了4个设备:ABCD,假设这4个设备都通过浏览器访问百度(假设都是使用内部端口80),那在路由器上会生成一张NAT映射表,浏览器返回数据在通过路由器的时候就通过这张映射表找到对应的内部设备。
从表中我们可以看到,这些设备映射后的外网IP地址是相同的(即路由器的外网IP地址),但是端口不同。因此浏览器在返回数据的时候,通过IP+端口,就可以确定唯一的一台设备(其实这也是NAT技术能实现多个设备只使用一个公网地址就能独立上网的基本原理)。同理,如果这时候小明想和设备A通信,那小明只需要向设备A映射的公网地址信息:36.23.223.162:8081发起连接就可以了。
因此,如果能将内网设备通过NAT方式映射到公网上,并获取映射后的公网IP地址及对应的端口号,那么也就实现了P2P通信的第一步。想要实现内网设备对公网地址的映射,除了常见的主动访问某个知名网站之外,还可以通过STUN协议来实现。
3.2 STUN协议
图5
STUN协议如图5所示:设备通过给公网的STUN服务器发送请求获得自己的公网地址信息。类似的,像这种通过某种协议或者方式让路由器留下一个内外网映射的“洞口”,通常称为:“打洞”。而外网主机如果可以通过这个“洞口”与内网主机通信,则说明“打洞成功”。
3.3 信令服务器
通过STUN协议可以获取到设备本身的外网IP地址和端口,只是完成了P2P通信的第一步。第二步则是如何将自己的外网IP地址和端口告诉对端。通常我们需要借助信令服务器来实现。通用的方案如图6所示:
图6
- 步骤1:IPC通过STUN协议获取到了自己的公网地址信息:36.23.223.162 : 8081;
- 步骤2:IPC将自己的地址信息发给信令服务器,信令服务器则将地址信息转发给“和家亲APP”;
- 步骤3:“和家亲APP”获取到对端的地址信息后,发起连接;由于路由器已经有IPC的地址映射,所以发起的连接会转发给IPC设备,至此就实现了“和家亲app”和IPC的P2P连接。
关于信令服务器,这边需要需要说明一下。一般来说设备启动时就会主动连接信令服务器,之后会保持与信令服务器的长连接;app也会保持与信令服务器的连接;通过信令服务器可以实现IPC与app的通信,目前信令服务器使用的协议是websocket。
4扩展
图6的几个步骤对于快速理解P2P的原理是有帮助的,但是也省略了很多内部细节,这个章节会将一些遗留的知识点补充回来。
思考一个问题:通过STUN协议获取到的公网IP地址和端口,对端就一定能连接成功吗?很显然答案是否定的。否则也就不会有“打洞成功率”的概念了。为了理解这点,首先需要了解NAT类型。
4.1 NAT类型
目前常见的NAT可以分成4种类型:
- 完全锥型
- IP 限制锥型
- 端口限制锥型
- 对称型
这4种类型中,越往后的NAT类型穿越难度越大。
4.1.1 完全锥型
完全锥型特点:一旦打洞成功,所有知道该洞的主机都可以通过它和内网主机通信。
4.1.2 IP 限制锥型
IP 限制锥型特点:IP限制锥型要比完全锥型严格,打洞成功后,只有与之打洞成功的外网主机才能通过该洞与内网主机通信,而其他外网主机哪怕知道这个洞口也不能通信。
4.1.3 端口限制锥型
端口限制锥型特点:端口限制锥型则要比IP限制锥型更严格,打洞成功后,除了要检测IP地址之外还要检测端口号。二者中只要有一项不满足,都无法通过该洞口进行通信。
4.1.4 对称型
完全锥型特点:内网主机每次访问不同的外网主机时,都会生成一个新的洞。而前面3种锥型使用的是同一个洞。
不同NAT类型的路由器其穿越表如下所示:
所以,前面例子中我们其实是将路由器的NAT类型默认假设成完全锥型。但是现实中,除了完全锥型外,我们还需要处理其他类型的路由器。
4.2 TURN协议
当两端路由器的NAT类型是:(端口限制锥型,对称型)或者(对称型,对称型)时,使用STUN协议就无法穿越,这个时候就需要使用TURN协议。TUAN协议简单来说就是进行数据转发,两个内网主机分别把内容发给TURN服务器,TURN服务器再将内容分别转发给对端,以此来实现通信。这边不再进行赘述。
5总结
P2P打洞的大致流程主要就是以下两个步骤:
- 处在内网的设备通过STUN/TURN协议获取到自身的内外网地址信息;
- 将相关的地址信息通过信令服务器发送给对端,对端拿到对应的地址信息后,尝试连接。
在实际过程中,进行P2P打洞的设备不仅获取外网的地址信息,也会获取内网的地址信息,同时也获取TRUN服务器分配的地址信息,生成候选地址对,候选地址对也有连接的优先级的概念,一般来说所有的候选地址对,都会尝试连接。
由于P2P协议涉及内容比较多,既需要了解底层的网络原理,也需要了解类似STUN和TUAN协议的内容。而且P2P协议打洞成功的关键很多时候与设备所处的网络环境有关,假如设备和app都处在对称型路由器之下,那打洞成功概率就会很低,并且由于P2P流程比较长,因此对于不了解其原理的开发人员来说定位起来会比较困难。
基于以上原因,目前中国移动智慧家庭运营中心的移动看家设备,已经升级至全新的流媒体传输协议——SRT。但是这并不妨碍我们了解P2P的实现原理。关于SRT协议的介绍,请期待之后的文章。