经过前面几部分的铺垫,你应该对P2P音视频互动的过程有了一个大概的了解,有可能你会觉得过程比较繁琐,甚至涉及到了网络底层。但是,不要担心,WebRTC已经帮我们做了很多的事情,让我们在音视频开发时变得轻而易举。那么WebRTC到底是什么呢?
WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。
WebRTC并不是Google原来自己的技术。在2010年,Google以大约6820万美元收购了VoIP软件开发商Global IP Solutions公司,并因此获得了该公司拥有的WebRTC技术。如今,互联网的音频、视频通信服务技术一般都是私有技术,如Skype, 需要通过安装插件或者桌面客户端来实现通信功能。Google希望Web开发人员能够直接在浏览器中创建视频或语音聊天应用,Global IP Solutions公司之前已经针对Android、Windows Mobile、iPhone制作了基于WebRTC的移动客户端。Google此次将WebRTC开源出来,就是希望浏览器厂商能够将该技术直接内嵌到浏 览器中,从而方便Web开发人员。
概念补充
除了之前提到的概念之外,再来补充几个相关的概念
交互式连接设施
交互式连接设施(Interactive Connectivity Establishment, ICE):允许你的浏览器和对端浏览器建立连接的协议框架。在实际的网络当中,有很多原因能导致简单的从A端到B端直连不能如愿完成。这需要绕过阻止建立连接的防火墙,给你的设备分配一个唯一可见的地址(通常情况下我们的大部分设备没有一个固定的公网地址),如果路由器不允许主机直连,还得通过一台服务器转发数据。你可能已经发现这个ICE就是我们之前STUN、TURN等连接方式的汇总,正式由于ICE框架,大大简化了我们的开发工作,ICE会按照优先级自动选择连接方式;
信令服务器
信令服务器(signal server):交换Peer之间的可通讯地址,通过STUN获取到自己的通讯地址之后,注册在信令服务器上就可以交换设备之间的通讯地址,从而完成P2P连接;
会话描述协议
会话描述协议(Session Description Protocol, SDP):描述多媒体连接内容的协议,例如分辨率,格式,编码,加密算法等。在开始P2P连接之前需要先协商双方共同支持的会话协议。当用户对另一个用户启动WebRTC调用时,将创建一个称为提议(offer)的特定描述。 该描述包括有关呼叫者建议的呼叫配置的所有信息。 接收者然后用应答(answer)进行响应,这是他们对呼叫结束的描述。 以这种方式,两个设备彼此共享以便交换媒体数据所需的信息;一个SDP描述的内容是这样的(“=”两边不能有空格)
v=0 o=- 212360934117607227 2 IN IP4 127.0.0.1 s=- t=0 0 m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126 a=rtpmap:111 opus/48000/2 ...... m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 121 127 120 125 107 108 109 35 36 124 119 123 118 114 115 116 a=rtpmap:96 VP8/90000 ...... 复制代码
一个SDP描述由一个会话和多个媒体描述组成,会话描述是v=开始到第一段媒体描述(1-4行),媒体描述是从m=到下一个媒体描述之前(5-6行——音频、8-9行——视频)。
会话级描述
会话描述字段比较多,最主要的有4个字段
- v=:UDP的版本号,不包含次版本
- o=:是一个会话发起者的描述
o=
<username>
:用户名,当不关心用户名时,可以用 “-” 代替 ;<session id>
:数字串,在整个会话中,必须是唯一的,建议使用 NTP 时间戳;<version>
:版本号,每次会话数据修改后,该版本值会递增;<network type>
:网络类型,一般为“IN”,表示“internet”;<address type>
:地址类型,一般为 IP4;<address>
:IP 地址
- Session Name:表示一个会话
- t=:开始时间和结束时间的描述,
t=<start time> <stop time>
,两个事件均为0时表示持久会话
WebRTC中的SDP
WebRTC下对SDP做了一些修改,在原有的基础上增加了一些其他描述
// 音频使用9端口收发; // UDP / TLS / RTP / SAVPF 表示使用 dtls / srtp 协议对数据加密传输; m = audio 9 UDP / TLS / RTP / SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126 // 网络描述, webRTC不使用 c = IN IP4 0.0.0.0 // 设置rtcp地址和端口, webRTC不使用 a = rtcp: 9 IN IP4 0.0.0.0 // 安全验证信息 a=ice-ufrag:duP8 a=ice-pwd:/7pIrSvgESATKPZUVzHhLQ0E a=ice-options:trickle // 音频流媒体描述 a=rtpmap:111 opus/48000/2 a=rtcp-fb:111 transport-cc a=fmtp:111 minptime=10;useinbandfec=1 a=rtpmap:103 ISAC/16000 a=rtpmap:104 ISAC/32000 a=rtpmap:9 G722/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:106 CN/32000 a=rtpmap:105 CN/16000 a=rtpmap:13 CN/8000 a=rtpmap:110 telephone-event/48000 a=rtpmap:112 telephone-event/32000 a=rtpmap:113 telephone-event/16000 a=rtpmap:126 telephone-event/8000 复制代码
媒体描述
- m=:表示一个会话,
m=<media> <port> <transport> <fmt list>
<media>
:媒体类型,比如 audio/video 等;<port>
:端口;<transport>
:传输协议,有两种——RTP/AVP 和 UDP;<fmt list>
:媒体格式,即数据负载类型 (Payload Type) 列表。
- a=*:
a=<type>
或者a=<type>:<value>
,type有两种类型rtpmap和fmap
现在我们来完善一下之前网关那里的示意图,添加上这里的几个概念
收集候选地址
所谓的收集候选地址,就是通过之前说到的STUN服务器来获取自身的可通讯地址。
类型 | 别名 | 如何传给对端 | 用法 |
主机候选项 | host | 信令服务器 | 从网卡中获取的本地传输地址,如果此地址位于NAT之后,则为内网地址 |
服务器反射候选项 | srflx | 信令服务器 | 从发送给Stun服务器的Binding检查中获取的传输地址。如果此地址位于NAT之后,则为最外层NAT的公网地址 |
对端反射候选项 | prflx | Stun Binding请求 | 从对端发送的Stun Binding请求获取的传输地址。这是一种在连接检查期间新发生的候选项 |
中继候选项 | relay | 信令服务器 | 媒体中继服务器的传输地址。通过使用TURN Allocate请求获取 |
交换候选地址
A通过信令服务器把第一步收集到的候选地址发送给B,B也将收集到的候选地址发送给A,A在接收到B的
所有候选地址之后会将自身候选地址与对端候选地址进行全排列,存储到状态表中。比如A此时的host是192.168.0.100:60000、srflx是11.102.30.3:30110,B的host是192.168.0.15:10001、srflx是1.10.108.25:30110,状态表如下
本地网卡地址 | 对端地址 | 状态 |
192.168.1.105:60001 | 192.168.0.204:40001 | 未进行过Stun检查 |
172.16.40.6:60003 | 192.168.0.204:40001 | 未进行过Stun检查 |
192.168.1.105:60001 | 11.92.14.8:50002 | 未进行过Stun检查 |
172.16.40.6:60003 | 11.92.14.8:50002 | 未进行过Stun检查 |
192.168.1.105:60001 | 192.168.0.181:40003 | 未进行过Stun检查 |
172.16.40.6:60003 | 192.168.0.181:40003 | 未进行过Stun检查 |
此时所有的记录状态都是未进行STUN检查,下一步就会进行每条记录的STUN检查。
STUN检查
STUN检查的过程我们之前有过介绍,如有遗忘可以再温习一下p2p打洞
连接,启动媒体
STUN检查结束之后开始准备连接,此时P2PTransportChannel中的状态表已经记录了每条记录所需要花费的成本(涉及到很多因素,比如发出Stun请求到收到应答经过了的时间……)。
**当有视频Rtp数据要发送时,检查状态表的第一条记录,如果判断出它的状态是发送就绪,就会用此Connection进行发送。否则直接放弃这个发送任务。**也就是说,媒体模块的任务不会受连接状态的影响,只是在要发送是检查状态,如果未连接则放弃发送。
为确保NAT映射和过滤规则不在媒体会话期间超时,ICE会不断通过使用中的候选项对发送Stun连接检查。通俗来说也就是“轮询”,如果STUN的响应超时,则会在增加成本,体现在状态表中就是优先级降低,即P2PTransportChannel状态表是实时的。