WebRTC 介绍

备注: 此页面正在建设中,部分内容会移至其他页面,因为 WebRTC 指导资料已经建成。

WebRTC 允许你将任意数据,音频或视频(或其任何组合)的点对点通信构建到浏览器应用程序中。在本文中,我们将介绍一个 WebRTC 会话的生命周期,从建立连接到不再需要时关闭连接。

创建连接

互联网很大 很大。那么多年以前,聪明的人看到它有多大,增长速度有多快,32 位 IP 寻址系统的局限性,并意识到有些事情要做,所以他们开始设计一个新的 64 位寻址系统。但是他们意识到,完成转换需要更长时间才能持续 32 位地址,所以其他一些机智的人们想出了让多台计算机共享同一个 32 位 IP 地址的方法。网络地址转换(NAT)是通过操纵 LAN 上的所有设备的数据出入的路由来支持这种地址共享的标准,所有这些设备都共享同一个 WAN(全局)IP 地址。

用户的问题是互联网上的每台个人计算机不再一定具有唯一的 IP 地址,实际上,每个设备的 IP 地址也会变,不仅可能由于设备从一个网络移动到另一个网络,也可能被 NAT 和/或 DHCP 改变。对于尝试进行点对点网络的开发人员,这引入了一个难题:没有每个用户设备的唯一标识符,不可能立即自动地知道如何连接到 Internet 上的特定设备。即使你知道你想谈论的人,你不一定知道如何到达他们,甚至也不知道他们的地址。

这就像你尝试向你的朋友 Michelle 发送一个包裹,但你只在这个包裹上贴了一个写着“Michelle”的标签,而你并不知道她的地址。你得查到她的地址并将其包装在包中,要不然她会在想为什么你又忘记她的生日了。

这就是信令(Signaling)的由来。

信令

信令是在两个设备之间发送控制信息以确定通信协议、信道、媒体编解码器和格式以及数据传输方法以及任何所需的路由信息的过程。关于 WebRTC 的信令流程最重要的一点是:**信令在规范中并没有定义。**所以开发者需要自己决定如何实现这个过程。开发者可以为应用程序引擎选择任意的信息协议(如 SIP 或 XMPP),任意双向通信信道(如 WebSocket 或 XMLHttpRequest) 与持久连接服务器的 API(如Google Channel API)一起工作。

你可能会想,为什么这么一个对于建立 WebRTC 连接至关重要的基本过程居然没有定义在规范里?答案很简单:由于两个设备无法直接相互联系,规范无法预测 WebRTC 的所有可能用例,因此更明智的做法就是让开发人员们自己选择合适的网络技术和消息传递协议。

尤其是如果一个开发人员已经有了一个连接两个设备的方法,那也没有必要强迫他们就为了 WebRTC 使用另一个规范定义的方法。由于 WebRTC 没有生活在真空中,所以可能还有其他的连接,因此,如果可以使用已有的连接通道,就可以避免添加额外的连接通道。

为了交换信令信息,你可以选择通过 WebSocket 连接来回发送 JSON 对象,或者你可以在适当的通道(Channel)上使用 XMPP 或 SIP,或者你可以通过 HTTPS 使用 XMLHttpRequest 进行轮询或者其他任何你可以想出来的技术组合。你甚至可以使用电子邮件作为信号通道。

还值得注意的是,用于执行信令的信道甚至不需要通过网络。一个 Peer 可以输出一个数据对象,这个数据对象可以被打印出来,然后物理携带(步行或由信鸽)直到进入另一个设备,然后由该设备输出响应,并以同种方式返回,直到 WebRTC 对等连接打开。这将带来非常高的延迟,但也是可以做到的。

信令期间交换的信息

信令期间需要交换的信息有三种基本类型:

  • 控制消息:用于设置、打开、关闭通信通道并处理错误。
  • 为了建立连接所需的信息:设备间能够彼此交谈所需的 IP 寻址和端口信息。
  • 媒体能力协商:交互双方可以理解哪些编解码器和媒体数据格式?这些都需要在 WebRTC 会议开始之前达成一致。

只有在信令成功完成之后,打开 WebRTC 对等连接的过程才真正开始。

值得注意的是,在信令期间,信令服务器实际上不需要理解两个设备之间交换的数据或者对这些数据做任何处理。信令服务器本质上就是一个中继器:两端连接的公共点,两端都知道它们的信令数据可以通过这个点来传输。服务器不需要以任何方式对此信息做出反应。

信令过程

为了开启一个 WebRTC 会话,以下事件需要依次发生:

  1. 每个 Peer 创建一个 RTCPeerConnection 对象,用来表示其 WebRTC 会话端。
  2. 每个 Peer 建立一个 icecandidate 事件的响应程序,用来在监测到该事件时将这些 candidates 通过信令通道发送给另一个 Peer。
  3. 每个 Peer 建立一个 track 事件的响应程序,这个事件会在远程 Peer 添加一个 track 到其 stream 上时被触发。这个响应程序应将 tracks 和其消受者联系起来,例如<video>元素。
  4. 呼叫者创建并与接收者共享一个唯一的标识符或某种令牌,使得它们之间的呼叫可以由信令服务器上的代码来识别。此标识符的确切内容和形式取决于你。
  5. 每个 Peer 连接到一个约定的信令服务器,如 WebSocket 服务器,他们都知道如何与之交换消息。
  6. 每个 Peer 告知信令服务器他们想加入同一 WebRTC 会话(由步骤 4 中建立的令牌标识)。
  7. 描述、候选地址等——之后会有更多

ICE 重连

有时,在 WebRTC 会话的整个生命周期内,网络条件会发生变化。其中一个用户可能会从蜂窝网络转移到 WiFi 网络,或者网络可能会变得拥塞。当这种情况发生时,ICE 代理可以选择执行 ICE 重连。在这个过程中网络连接会进行重新协商,与执行初始 ICE 协商的方式完全相同,除了:媒体继续流过原始网络连接直到新的开始运行。然后媒体转移到新的网络连接,旧的关闭。

不同的浏览器支持在不同情况下的进行 ICE 重连。例如,并不是所有的浏览器都会因为网络拥塞执行 ICE 重连。

ICE 重连有两个级别:全 ICE 重连会导致会话中的所有媒体流重新协商。 部分 ICE 重连允许 ICE 重新协商特定媒体流,而不是所有媒体流进行重新协商。然而,有些浏览器还不支持部分 ICE 重启。 <<<你如何触发每一个?>>>

如果你需要以某种方式更改连接的配置(例如更改为不同的 ICE 服务器集),你可以调用 RTCPeerConnection.setConfiguration() 设置新的 RTCConfiguration 字典,然后重新启动 ICE。

要明确触发 ICE 重新启动,只需通过调用 RTCPeerConnection.createOffer() 启动一个协商过程,同时指定 iceRestart 选项为 true。然后就像平时那样处理连接过程即可。

发送

getUserMedia(获取用户媒体)

LocalMediaStream object

接收

WebRTC 在 Firefox 浏览器的偏好选择选项是隐藏的。可以到 about:config 这个页面设置 'media.navigator.enabled' 为 'true'。

备注: 在 Source tree 中有一些测试文件可以提供给你关于 WebRTC 如何工作的一个想法。具体例子请查看:dom/media/tests/local_video_test.html。你也可以尝试 服务器 demo ,源代码: server source