原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。javascript
这是 JavaScript 工做原理第十八章。html
何为 WebRTC ?首先,字面上已经给出了关于这一技术的大量信息,RTC 即为实时通讯技术。html5
WebRTC 填补了网页开发平台中的一个重要空白。在以往,只有诸如桌面聊天程序这样的 P2P 技术才可以实现实时通信而网页不行。可是 WebRTC 的出现改变了这一情况。java
WebRTC 本质上容许网页程序建立点对点通讯,咱们将会在随后的章节中进行介绍。咱们将讨论以下主题,以便向开发者全面介绍 WebRTC 的内部构造:git
每一个用户的网页浏览器必须按照以下步骤以实现经过网页浏览器进行的点对点通讯:github
众所周知,基于浏览器的点对点通讯的最大挑战之一即如何定位和创建与另外一个网页浏览器进行通讯的网络套接字以进行双向数据传输。咱们将会克服创建与此种网络链接相关的困难。web
每当网页程序须要数据或者静态资源,会直接从相应的服务器获取,仅此而已。可是,若是若想要经过直接链接用户的浏览器来创建点对点的视频聊天就不可能,由于其它浏览器并非一个已知的网页服务器,因此用户不知道须要创建视频聊天的 IP 地址。因此,须要更多的技术以创建 p2p 链接。promise
通常电脑是不会被分配一个静态公共 IP 地址的。缘由是电脑是位于防火墙和网络访问转换设备(NAT) 后面的。浏览器
一个 NAT 设备会把防火墙内的私有 IP 地址转换为一个公共 IP 地址。对于安全和有限的可用公共 IP 地址来讲,NAT 设备是必须的。这也是为何开发者的网页程序不可以把当前设备当作拥有一个静态公共 IP 地址的缘由。安全
让咱们来了解下 NAT 设备的工做原理。当开发者处于一个企业网中而后加入了 WIFI,那么电脑将会被分配一个只存在于 NAT 后面的 IP 地址。假设是 172.0.23.4。然而,对于外部而言,用户的 IP 地址会是相似 164.53.27.98 这样的。那么,外部会把全部请求看做来自 164.53.27.98 而 NAT 设备会保证来自于目标用户电脑的请求的响应数据返回到相应的内部 172.0.23.4 IP 地址的电脑。这得归功于映射表。注意到除了 IP 地址,网络通讯还须要通讯端口。
随着 NAT 设备参与其中,浏览器须要知道进行通讯的目标浏览器对应的机器 IP 地址。
这个就须要用到 NAT 会话穿透程序(STUN)和 NAT 穿透中继转发服务器。为使用 WebRTC 技术,开发者须要请求 STUN 服务器以得到其公共 IP 地址。这就好像你的电脑请求远程服务器,询问远程服务器发起查询的客户端 IP 地址。远程服务器会返回对应的客户端 IP 地址。
假设这一过程进展顺利,那么开发者将会得到一个公共 IP 地址和端口,这样就能够告知其它点如何直接和你进行通讯。同理,这些点也能够请求 STUN 或 TURN 服务器以得到公共 IP 地址而后告知其通讯地址。
前述网络信息检索过程只是更大的信令话题的一部分,在 WebRTC 中,它是基于 JavaScript 会话构建协议(JSEP)标准的。信令涉及网络检索和 NAT 穿透,会话建立及管理,通讯安全,媒体功能元数据和调制及错误处理。
为了让通讯顺利进行,节点必须肯定元数据本地媒体环境(好比分辨率和编码能力等)和收集可用的程序主机网络地址。WebRTC 接口里面没有集成反复传输这一重要信息的信令机制。
WebRTC 标准并无规定信令且没有在接口中实现是为了可以更加灵活地使用其它技术和协议。信令和处理信令的服务器是由 WebRTC 程序开发者控制的。
假设开发者基于浏览器的 WebRTC 程序使用以前所说的 STUN 服务器获取其公共 IP 地址,那么,下一步即和其它点进行协商和创建网络会话链接。
使用任意一个专门应用于多媒体通讯的信令/通讯协议初始化会话协商和通讯链接。该协议负责管理会话和中断的规则。
会话初始协议(SIP) 是协议之一。多亏了 WebRTC 信令的灵活性,SIP 并非惟一可供使用的信令协议。所选的通讯协议必须和被称为会话描述协议(SDP)的应用层协议兼容,SDP 被应用于 WebRTC。全部的多媒体指定元数据都是经过 SDP 协议进行数据传输的。
任意试图和其它点进行通讯的点(好比 WebRTC 程序)都会生成交互式链接创建协议(ICE)候选集。候选集表示一个可供使用的 IP 地址,端口及传输协议的集合。注意,一台电脑能够拥有多个网络接口(有线和无线等),所以能够拥有多个 IP 地址,每一个接口分配一个 IP 地址。
如下为 MDN 上描绘这一通讯交换的图示:
每一个节点首先获取以前所说的公共 IP 地址。以后动态建立「信道」信令数据来检索其它节点而且支持点对点协商及建立会话。
这些「信道」不可以被外部检索和访问到且只能经过惟一标识符来访问。
须要注意的是因为 WebRTC 的灵活性且事实上信令建立程序并无在标准中指定,使用的技术不一样,「信道」的概念和使用会有些许异同。事实上,一些协议并不要求「通道」机制来进行通讯。
本篇文章将会假设存在「信道」。
一旦两个或者更多的点链接到相同的「信道」上,节点就能够进行通讯和协商会话信息。这一过程和发布/订阅模式有些许相似。大致上,初始点使用诸如会话初始协议(SIP)和 SDP 的信号协议发出一个「offer」的包。发起者等待链接到指定「通道」的接收者的「answer」应答。
一旦接收到应答,会开始选择和协商由各个节点生成的最优交互链接创建协调候选(ICE)集。一旦选定了最优 ICE 候选集,特别是确认了全部节点通讯所要求的元数据,网络路由(IP 地址和端口)及媒体信息。这样就会彻底创建及激活节点间的网络套接字会话。紧接着,每一个节点建立本地数据流和数据通道端点,而后,最后使用任意双向通讯技术来传输多媒体数据。
若是确认最优 ICE 候选的过程失败了,这样的状况常常发生于使用的防火墙和 NAT 技术,后备使用 TURN 服务器做为中继转发服务器。这一过程主要是使用一台服务器做为中间媒介,而后在节点间转发传输数据。请注意这不是真正的点对点通讯,由于真正的点对点通讯是节点之间直接进行双向数据传输。
每当使用 TURN 做为后备通讯的时候,每一个节点将没必要知道如何链接并传输数据给对方节点。相反,节点只须要知道在会话通讯期间实时发送和接收多媒体数据的公共 TURN 服务器。
须要重点理解的是这仅仅只是一个失败保护和最后手段。TURN 服务器须要至关健壮,拥有昂贵带宽和强大的处理能力及处理潜在的大量数据。所以,使用 TURN 服务器会明显增长额外的开销和复杂度。
WebRTC 中包含三种主要接口:
咱们将分别介绍这三类接口。
媒体捕捉和流接口常常被称为媒体流接口或者流接口,该接口支持音频或者视频数据流数据,处理音视频流的方法,与数据类型相关的约束,异步获取数据时的成功和错误回调及 API 调用过程当中触发的事件。
MediaDevices 的 getUserMedia() 方法提示用户受权容许使用媒体输入设备,建立一个包含指定媒体类型轨道的媒体流。该媒体流,可包括诸如视频轨道(由诸如摄像机,视频录制设备,屏幕共享服务等硬件或者虚拟视频源所建立),音频轨道(与视频相似,由诸如麦克风,A/D 转换器等的物理或者虚拟音频源所建立)且有多是其它类型轨道。
该方法返回一个 Promise 并解析为 MediaStream 对象。当用户拒绝受权或者没有可用的匹配媒体资源,promise 会分别返回 PermissionDeniedError 或者 NotFoundError。
能够经过 navigator
对象访问 MediaDevice 单例:
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
/* 使用流 */
})
.catch(function(err) {
/* 处理错误 */
});
复制代码
注意这里须要传入 constraints
对象以指定返回的媒体流类型。开发者能够进行各类配置,包括使用的摄像头(前置或后置),帧频率,分辨率等等。
从版本 25 起,基于 Chromium 的浏览器已经容许经过 getUserMedia()
获取的音频数据赋值给音频或者视频元素(但须要注意的是媒体元素默认值为空)。
能够把 getUserMedia
做为网页音频接口的输入节点:
function gotStream(stream) {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContext();
// 从流建立音频节点
var mediaStreamSource = audioContext.createMediaStreamSource(stream);
// 把它和目标节点进行链接让本身倾听或由其它节点处理
mediaStreamSource.connect(audioContext.destination);
}
navigator.getUserMedia({audio:true}, gotStream);
复制代码
因为该接口可能致使明显的隐私问题,规范在通知用户和权限管理方面对 getUserMedia()
方法有很是明确的规定。在打开诸如用户网页摄像头或者麦克风的媒体输入设备的时候getUserMedia()
必须老是获取用户的受权。
浏览器可能提供每一个域名受权一次的权限功能,但必须至少第一次询问受权,而后用户必须指定受权的权限。
通知中的规则一样重要。除了可能存在其它硬件指示器,浏览器还必须显示一个窗口显示使用中的摄像头或者麦克风。即便当时设备没有进行录制,浏览器必须显示一个提示窗口提示已受权使用哪一个设备做为输入设备。
RTCPeerConnection 表示一个本地电脑和远程节点之间的 WebRTC 链接。它提供了链接远程节点,维护和监视链接及关闭再也不活跃的链接的方法。
以下为一张 WebRTC 图表展现 了 RTCPeerConnection 的角色:
从 JavaScript 方面看 ,图中须要理解的主要方面即 RTCPeerConnection
把复杂的底层内部结构的复杂度抽象为一个接口给开发者。WebRTC 所使用的编码和协议为即便在不稳定的网络环境下仍然可以建立一个尽量实时的通讯而作了大量的工做:
不只仅是音视频,WebRTC 还支持实时传输其它类型的数据。
RTCDataChannel
接口容许点对点交换任意数据。
该接口有许多用途,包括:
该接口有几项功能,充分利用 RTCPeerConnection
并建立强大和灵活的点对点通讯:
RTCPeerConnection
建立会话语法和已有的 WebSocket 相似,包含有 send()
方法和 message
事件:
var peerConnection = new webkitRTCPeerConnection(servers,
{optional: [{RtpDataChannels: true}]}
);
peerConnection.ondatachannel = function(event) {
receiveChannel = event.channel;
receiveChannel.onmessage = function(event){
document.querySelector("#receiver").innerHTML = event.data;
};
};
sendChannel = peerConnection.createDataChannel("sendDataChannel", {reliable: false});
document.querySelector("button#send").onclick = function (){
var data = document.querySelector("textarea#send").value;
sendChannel.send(data);
};
复制代码
因为通讯是直接在浏览器之间进行的,因此 RTCDataChannel 会比 WebSocket 更快即便是使用中继转发服务器(TURN)。
在实际应用中,WebRTC 须要服务器,但这很简单,所以会发生以下步骤:
换句话说,WebRTC 须要四种类型的服务端功能:
ICE 使用 STUN 协议及其扩展 TURN 协议来建立 RTCPeerConnection 链接来处理 NAT 穿透和其它网络变化。
如前所述,ICE 是用来链接诸如两个视频聊天客户的节点协议。一开始,ICE 会试图使用最低的可能的网络延迟即便用 UDP 来直接链接节点。在这一过程当中,STUN 服务器只有一个任务:让位于 NAT 以后的节点可以找到其公共地址和端口。开发者能够查看一下可用的 STUN 服务器(Google 也有一堆) 名单。
若 UDP 失败,ICE 尝试 TCP,先 HTTP 后 HTTPS。若是直接链接失败-特殊状况下,因为企业 NAT 穿透和防火墙-ICE 使用中间(转发) TURN 服务器。换句话说,ICE 首先经过 UDP 使用 STUN 服务器来直接链接节点,若失败则后备使用 TURN 中继转发服务器。「检索链接候选者」指的是检索网络接口和端口的过程。
实时通讯程序或者插件可能形成几种安全问题。例如:
WebRTC 有几种方法用来解决如上问题:
对于须要实现一些浏览器之间实时通讯流功能的产品而言,WebRTC 是一个使人难以置信和强大的技术。
参考资料:
今日头条招人啦!发送简历到 likun.liyuk@bytedance.com ,便可走快速内推通道,长期有效!国际化PGC部门的JD以下:c.xiumi.us/board/v5/2H…,也可内推其余部门!
本系列持续更新中,Github 地址请查阅这里。