本篇文章参考WebRTC基础知识详解_签约计划_IT酷盖_InfoQ写作社区,介绍了P2P音视频通信的场景下的一些基础知识,包括WebRTC的基本架构、协议栈,一对一通话基础,和一对一通话原理三部分。
WebRTC 的组件架构分为两层:应用层和核心层。上图中的绿色部分显示的是 WebRTC 提供的核心功能,而深紫色部分是浏览器提供的 JS 的 API(即浏览器对 WebRTC 核心层 C++ API 做了一层封装,封装成了 JS 接口)。
图片最上面的浅紫色指入箭头是上层应用,可以在浏览器中直接访问浏览器提供的 API,最终调用到核心层。
而关于核心功能层,主要是有 4 部分:
API数量较少,主要是PeerConnection。而 PeerConnection 的 API又包含传输质量、传输质量报告、各种统计数据、各种流等。(设计技巧:对于上层来说,提供的 API 简单,方便应用层开发;内部比较复杂。)
如应用创建了音频、视频、非音视频的数据传输,都可以在 Session 层做处理,做管理相关的逻辑。
引擎层/传输层(最重要、核心部分)
这部分分为 3 个不同的模块:Voice Engine(音频引擎)、Video Engine(视频引擎)以及Transport(传输模块),可用作音视频传输解耦。
Voice Engine(音频引擎)—— 包含了如音频采集、音频编解码、音频优化(包括降噪、回声消除等)等一系列的音频功能。
Video Engine(视频引擎)—— 包含了如视频采集、视频编解码、根据网络抖动动态修改视频传输质量、图像处理等。
Transport(传输模块) —— 在WebRTC中,对所有的音频视频进行接收与发送,传输层包括了泄漏的检测、网络链路质量检测,根据情况估算网络带宽,根据网络带宽进行音视频、文件等非音视频的传输。
硬件层
WebRTC的核心层中是没有视频的渲染的,所有的渲染都需要浏览器层自己做。
WebRTC 中的协议栈是已经写好了底层的代码,符合协议标准,提供给开发者一个功能模块进行调用的。开发者需只需要关心应用逻辑,数据从哪里到哪里,怎么存储,处理系统里设备之间的通信顺序等即可。
WebRTC利用多种标准和协议,包括数据流,STUN / TURN 服务器,信令,JSEP,ICE,SIP,SDP等。
信令
媒体协商
彼此若要进行通信,就需要先了解对方支持的媒体格式、支持的最大分辨率等媒体信息,如下图所示,peerA端可支持MPEG-1/2、H264多种编码格式,而peerB端支持MPEG-4、H264,要保证二端都正确的编解码,最简单的办法就是取它们的交集H264;
WebRTC中,SDP(Session Description Protocol)就是用来描述上述这类信息的协议。参与音视频通信的双方必须先交换SDP信息,该交换过程就是“媒体协商”。
网路协商
顾名思义,双方通信时,需要一条双方都能访问的链路,选择双方共用的网段来进行通信,该过程同样需要双方交换网络的相关信息,称作“网络协商”。
信令服务器
媒体协商与网络协商都是基于双方建立连接后,那么双方如何建立连接呢?这时候就用到信令服务器(Signal Server)了,一般搭在公网或者两端都可以访问到的局域网中。
信令通过应用层协议,WebSockets和HTTP等协议发送。
该图中,两个浏览器端的上层,可以抽象出一层信令服务器(1台或是多台),如果两端的浏览器都可以访问某个公共的网络环境(如公网),那么就可以令双方都连接到该公用的信令服务器上进行点对点的连接。见下图
但如果没有公共的网络环境,就需要两端各搭建一组服务器,这两组服务器借助公网中的信令服务器进行互通,就可以实现上面提到的SDP信息,以及网络信息的交换了。SDP的交换过程如下:
1、Amy(1个假想的人名),把自身的SDP信息,通过setLocalDescription
方法保存起来,然后通过offer
方法,发给信令服务器。
2、信息服务器把Amy的SDP向前传递到另1端的Bob(另1个假想的人名),Bob会先调用setRemoteDescripition
把Amy的SDP保存下来。
3、然后Bob调用setLocalDescription
方法保存自己的SDP,然后再通过answer
方法,把自己的SDP通过信令服务器发给Amy
4、Amy收到Bob的SDP后,调用setRemoteDescription
保存起来,这样双方就完成了SDP交换,然后找出其中的交集,如果能达成一致,就可以建立p2p连接,开始通讯了。
据webrtc笔记(2): 1对1实时视频/语音通讯原理概述 - 菩提树下的杨过 - 博客园 (cnblogs.com)一文中提到:
在中国的网络环境中,据一些统计数据显示,至少1半的网络是无法直接穿透打通的(我个人认为根本原因是:IP4地址资源在互联网发展早期绝大多数都被国外占用了,轮到中国这些发展中国家使用时IP地址严重不足,所以大多数电脑都不具备公网ip,只能通过路由器、交换机做NAT转换,而相当一部分NAT是对称型的,基本上没法空透)
那么这时候就要想了,搭建服务器的目的是为了与公共的信令服务器通信,那么不在同一个网络中的数据应该如何传输呢?见下图。
此时用到的技术是NAT,即网络地址转换。通过该技术实现网络穿越,令两台局域网设备连接到公网的信令服务器上。
转换原理并不复杂,可以参考我自己整理的这篇文章:
《图解TCP/IP》阅读笔记(第五章 5.6)—— NAT技术初探
基于UDP的P2P应用需要考虑NAT的类型,而关于NAT类型的博客,则可以参考这篇文章:
P2P学习(一)NAT的四种类型以及类型探测 - 山上有风景 - 博客园 (cnblogs.com)
这里根据这篇文章中所提到的场景,进行一个简单的归类:
大体上NAT的类型根据分配端口是是否复用旧的端口映射关系,分为两大类:锥形和对称型。而锥形又可以分为三种,见下面的1、2、3。
设定初始环境如下:
公网server1 ip是1.1.1.1, 监听端口是1111 公网server2 ip是2.2.2.2, 监听端口是2222 NAT router ip是8.8.8.8 NAT内部client是192.168.0.3
client发送数据的时候,不管是tcp还是udp必须本地绑定一个端口,一般来讲,这个过程都是自动的。假定client
192.168.0.3, 100
给 server1.1.1.1, 1111
发送报文,报文到达路由器,路由器在自己的公网ip上开辟一个端口800
,从而建立了一个映射关系8.8.8.8, 800
<—>192.168.0.3, 100
, 建立映射关系后,所以192.168.0.3, 100
和1.1.1.1, 1111
之间的报文都通过这个映射关系进行转发。见下图:关键点来了,若此时客户端
192.168.0.3, 100
又想给服务器2.2.2.2,2222
发送数据呢?按照刚刚所讲,分为两种情况:1, 复用旧的映射关系(8.8.8.8, 800)<--->(192.168.0.3, 100)和(2.2.2.2, 2222)通信;这就是锥型(Cone) NAT---(分为下面的3个小类) 2, 创建新的映射关系(8.8.8.8, 801)<--->(192.168.0.3, 100)和(2.2.2.2, 2222)通信; 这就是对称型NAT
而若已经建立好映射关系,服务器
2.2.2.2,2222
恰好发送数据给路由器8.8.8.8,800
,是否应该转发给192.168.0.3,100
呢?这时候就要分为四种情况了:
1, 无条件转发给(192.168.0.3, 100), 这就是全锥型(Full Cone)NAT。 2, 如果(192.168.0.3, 100)之前给(2.2.2.2)发送过数据,则转发, 这就是受限锥型(Restricted Cone)。 3, 如果(192.168.0.3, 100)之前给(2.2.2.2, 2222)发送过数据,则转发, 这就是端口受限锥型(Port Restricted Cone)。 4, 丢弃报文,拒绝转发, 这就是对称型NAT。
而在使用NAT技术的时候,需要使用STUN和TURN技术。
STUN(Simple Traversal of UDP Through NATs)
翻译:NAT的UDP简单穿越
诞生:RFC3489
使用UDP穿透NAT,属于一个轻量级的协议。该协议的作用是,令位于局域网中的客户端,找到自己的公网IP地址与端口号,这些信息用于在两个同时处于NAT路由器之后的局域网主机之间创建UDP通信。
简单来说,STUN技术用于给无法在公网环境下的视频通话设备分配公网IP和端口号,见下图:
但是STUN的问题就是,并不是每次都可以成功为NAT通话的设备分配IP地址,而TRUN可以解决这个问题。
TURN(Traversal Using Relays(中继) around NAT)
翻译:使用(NAT周围的)中继穿透
诞生:RFC5766
该技术是STUN的一个扩展协议。如果STUN未能成功地为需要NAT通话的设备分配IP地址,就需要公网的服务器作为一个中继,对客户端的数据进行转发,用于转发的协议就是TURN,其工作原理见下图:
使用这种方式在进行音视频通话时,带宽由服务器来承担,本地带宽压力较小。
ICE(Interactive Connectivity Establishment)
翻译:互动式连接建议
ICE并非是一种协议,而是一个框架,该框架整合了STUN和TURN,使各种NAT穿透技术可以实现统一。在该框架下,当需要穿越网络时,ICE会先尝试STUN,查出属于哪种类型的NAT之后,以及NAT要使用的某一个本地端口绑定的Internet端端口,从而建立UDP连接。如果该过程失败,ICE就会再次尝试TCP(先尝试HTTP,再尝试安全性更高的HTTPS)。如果仍然失败,就使用中继的TURN服务器。
由此,ICE可以实现在未知网络拓扑结构中实现设备互连。另外,由于该技术不需要为VoIP(基于IP的语音传输,Voice over Internet Protocol)流量手动打开防火墙,所以也不会产生潜在的安全隐患。
ICE的框架如下图所示:
该篇博客中详细介绍了STUN、TURN和ICE:
P2P技术详解(三):P2P技术之STUN、TURN、ICE详解(转载) - 简书 (jianshu.com)
(该图的上半部分即是SDP信息交换过程,下半部分就是在ICE框架下,实现网络协商和媒体数据的传输)
在看完 1 对 1 音视频通话基础后再来看通话实现原理就比较简单了。具体步骤如下:
1、双方先调用 getUserMedia
打开本机摄像头。
2、向信令服务器发送加入房间请求。
3、信令服务器通知本人加入成功,同时向其它人广播加入消息。
4、二端开始创建peerConnection
连接。
5、peerA 端创建 offer
,同时将 SDP 保存到本机(setLocalDescription
),并通过信令服务器传递到 peerB。
6、peerB 在 setLocalDescription
后,会异步触发“候选网络链路”收集,大致是通过 STUN 确定自己所有的 NAT 映射出口,如果 STUN 返回 NAT 是“对称型”的,基本上就没法穿透了,会再通过 TURN 拿到中继Reply
地址,并通过信令服务器,将网络候选链路信息发到 peerA,即开始网络协商。
此处需要说明一下什么叫做候选链路信息,有的文章中会将之称为ICE候选者(这也是最普遍的中文译名),之所以会有候选,是因为一个对等方可能有很多通信传输。某个用户可能有多个私有IP /端口,和/或多个公共IP /端口,和/或各种协议,和/或一个或多个反向代理等等。一旦我们创建了SDP产品,WebRTC就会尝试查找每个可能的通信传输到浏览器,这被称为 ICE 候选 对象( 交互式连接建立),以实际的RTCIceCandidate实例为例:
ICE候选对象仅仅是应该添加到SDP中的另一个键值组。我们可以等待WebRTC找到每个可能的候选者并发送完整的SDP,或者我们可以与信令服务器一起发送每个检测到的ICE候选对象并逐步扩展SDP;或者这两个选项均有效。WebRTC应该知道如何在ICE之间轮换并选择最可行的选项。
7、peerA 收到的 peerB 的 SDP 后,开始回应(createAnswer
),仍然通过信令服务器,将 SDP 发送到 peerB
8、同时 peerA 也会开始网络候选链路的收集,并将自己的网络信息,通过信令服务器,发到 peerB。
这样 peerA,peerB 就相互交换了媒体信息及网络信息,如果能达到一致(找到交集),就可以开始通讯了。
本篇文章从三个方面介绍了与P2P音视频对话相关的基础知识。
WebRTC基本架构、协议栈
本节简要介绍了其基本架构与涉及到的主要协议,作为后文内容的铺垫。
一对一音视频通话基础
本节介绍了媒体协商、网络协商、信令服务器与SDP(Session Description Protocol)的概念;
并简要介绍了NAT(Network Address Translation)技术,实现内外网穿透;
基于NAT技术的STUN(Simple Traversal of UDP Through NATs),基于UDP实现为内网环境下分配公网IP;
TURN(Traversal Using Relays around NATs)技术,当STUN无法获得IP地址时,就通过查找NAT路由器附近的中继服务器来完成通信;
ICE(Interactive Connectivity Establishment),一个用于在未知网络拓扑结构中实现设备互连的框架。
一对一音视频通话原理实现
通过本节的流程图, 可以明晰此前所讲的,一对一环境下媒体协商、网络协商、ICE实现互联的过程。