WebRTC 会话的生命周期
WebRTC 允许您将任意数据、音频或视频(或它们的任意组合)的点对点通信集成到浏览器应用程序中。在本文中,我们将探讨 WebRTC 会话的生命周期,从建立连接到在不再需要时关闭连接。
本文不深入介绍建立和处理 WebRTC 连接所涉及的实际 API 细节;它概述了通用流程,并提供了一些关于为什么需要每个步骤的信息。有关实际示例和代码功能的分步说明,请参阅 信令与视频通话。
注意: 此页面目前正在建设中,随着 WebRTC 指南材料的构建,部分内容将移至其他页面。敬请谅解!
建立连接
互联网很大。非常大。它如此之大,以至于多年前,聪明人看到了它的规模、它的快速增长,以及 32 位 IP 地址系统的局限性,并意识到必须采取措施,在我们用完地址之前,所以他们开始设计一个新的 64 位地址系统。但他们意识到,完成过渡所需的时间将比 32 位地址的寿命长,因此其他聪明人想出了一种方法,让多个计算机共享同一个 32 位 IP 地址。网络地址转换(NAT)是一种通过处理进出局域网设备的数据路由来支持此地址共享的标准,这些设备都共享一个 WAN(全局)IP 地址。
用户面临的问题是,互联网上的每个单独计算机不再必然拥有唯一的 IP 地址,事实上,每个设备的 IP 地址不仅可能在它们从一个网络移动到另一个网络时发生变化,而且如果它们的网络地址被NAT 和/或 DHCP 更改,也会发生变化。对于试图进行点对点网络开发的开发者来说,这引入了一个难题:没有每个用户设备的唯一标识符,就无法即时自动地知道如何在互联网上连接到特定设备。即使您知道您想与谁交谈,您也不一定知道如何联系他们,甚至不知道他们的地址是什么。
这就好比您想给朋友 Michelle 寄包裹,但只写着“Michelle”就把它扔进邮箱,而您不知道她的地址。您需要查找她的地址并将其写在包裹上,否则她会想知道为什么您又忘了她的生日。
这就是信令的作用所在。
信令
信令是两个设备之间发送控制信息的处理过程,以确定通信协议、信道、媒体编解码器和格式、数据传输方法以及任何必需的路由信息。关于 WebRTC 信令过程最重要的一点是:它没有在规范中定义。
您可能会想,为什么建立 WebRTC 连接的基本过程之一会遗漏在规范之外?答案很简单:由于两个设备之间没有直接联系的方式,而且规范无法预测 WebRTC 的所有可能用例,因此让开发人员选择合适的网络技术和消息协议更有意义。
特别是,如果开发人员已经有一种连接两个设备的方法,那么为 WebRTC 强制使用另一种由规范定义的连接方式就没有意义了。由于 WebRTC 并非孤立存在,很可能还有其他连接方式在起作用,因此如果可以使用现有信道,则避免为信令添加额外的连接信道是有意义的。
为了交换信令信息,您可以选择通过 WebSocket 连接来回发送 JSON 对象,或者可以使用 XMPP 或 SIP 通过合适的信道,或者可以使用 fetch() 和 HTTPS 进行轮询,或者您能想到的任何其他技术组合。您甚至可以使用电子邮件作为信令信道。
另外值得注意的是,用于执行信令的信道甚至不需要通过网络。一个对等方可以输出一个数据对象,该对象可以被打印出来,物理携带(步行或通过信鸽)到另一个设备,然后输入到该设备,接着该设备输出一个响应,然后步行返回,如此循环,直到 WebRTC 对等连接打开。这将有很高的延迟,但理论上是可行的。
信令过程中交换的信息
在信令过程中需要交换三种基本类型的信息:
- 用于设置、打开和关闭通信信道以及处理错误的控制消息。
- 设置连接所需的信息:对等方能够相互通信所需的 IP 地址和端口信息。
- 媒体能力协商:对等方能够理解哪些编解码器和媒体数据格式?在 WebRTC 会话开始之前需要就这些达成一致。
只有在信令成功完成后,才能开始打开 WebRTC 对等连接的实际过程。
值得注意的是,信令服务器实际上不需要理解或处理两个对等方在信令过程中通过它交换的数据。信令服务器本质上是一个中继:一个双方连接的共同点,它们知道它们的信令数据可以通过它传输。服务器不需要以任何方式响应此信息。
信令过程
为了开始 WebRTC 会话,必须按顺序执行一系列操作:
- 每个对等方创建一个
RTCPeerConnection对象,代表其在 WebRTC 会话中的一端。 - 每个对等方为
icecandidate事件建立一个处理程序,该处理程序负责通过信令信道将这些候选者发送到另一个对等方。 - 每个对等方为
track事件建立一个处理程序,当远程对等方将轨道添加到流时会收到该事件。此代码应将轨道连接到其使用者,例如<video>元素。 - 呼叫者创建一种标识符或令牌,并与接收方对等方共享,以便信令服务器上的代码可以识别它们之间的通话。此标识符的确切内容和形式由您决定。
- 每个对等方连接到一个约定好的信令服务器,例如它们都知道如何与之交换消息的 WebSocket 服务器。
- 每个对等方告知信令服务器它们想加入同一个 WebRTC 会话(通过步骤 4 中建立的令牌标识)。
- 描述、候选者等 — 更多内容即将发布
ICE 重启
有时,在 WebRTC 会话的生命周期中,网络条件会发生变化。例如,一个用户可能从蜂窝网络切换到 Wi-Fi 网络,或者网络可能变得拥塞。当这种情况发生时,ICE 代理可能会选择执行ICE 重启。这是一个重新协商网络连接的过程,与初始 ICE 协商的方式完全相同,只有一个例外:媒体在新的网络连接启动并运行时继续通过原始网络连接传输。然后,媒体切换到新的网络连接,旧的连接被关闭。
注意: 不同的浏览器在不同的条件下支持 ICE 重启。例如,并非所有浏览器都会因网络拥塞而执行 ICE 重启。
下面对 failed ICE 连接状态的处理程序展示了如何重启连接。
pc.oniceconnectionstatechange = () => {
if (pc.iceConnectionState === "failed") {
pc.setConfiguration(restartConfig);
pc.restartIce();
}
};
代码首先使用更新后的配置对象调用 RTCPeerConnection.setConfiguration()。如果需要以某种方式更改连接配置(例如更改为不同的 ICE 服务器集),则应在重启 ICE 之前完成此操作。
然后,处理程序调用 RTCPeerConnection.restartIce()。这会告诉 ICE 层在下一次 createOffer() 调用中自动添加 iceRestart 标志,从而触发 ICE 重启。它还会为 ICE 用户名片段(ufrag)和密码生成新值,这些值将用于重新协商过程和由此产生的连接。
当检测到 ICE ufrag 和 ICE 密码的新值时,连接的应答方将自动开始 ICE 重启。