使用 WebRTC 数据通道

在本指南中,我们将探讨如何向对等连接添加数据通道,该通道可用于安全地交换任意数据;也就是说,我们可以选择任何格式来交换我们想要的任何类型的数据。

注意: 由于所有 WebRTC 组件都必须使用加密,因此在 RTCDataChannel 上传输的任何数据都会自动使用数据报传输层安全 (DTLS) 进行保护。有关更多信息,请参见下文的 安全

创建数据通道

RTCDataChannel 使用的底层数据传输可以通过以下两种方式之一创建:

  • 让 WebRTC 为您创建传输并将其宣告给远程对等端(通过使其接收 datachannel 事件)。这是简单的方法,适用于多种用例,但可能不够灵活,无法满足您的需求。
  • 编写自己的代码来协商数据传输,并编写自己的代码来向另一方对等端发出信号,表明它需要连接到新通道。

让我们分别看看这两种情况,从最常见的第一种开始。

自动协商

通常,您可以允许对等连接为您处理 RTCDataChannel 连接的协商。为此,请调用 createDataChannel(),而不为 negotiated 属性指定值,或者将该属性指定为 false。这将自动触发 RTCPeerConnection 为您处理协商,从而使远程对等端创建一个数据通道,并将两者在网络上连接起来。

createDataChannel() 会立即返回 RTCDataChannel 对象;您可以通过监听发送到 RTCDataChannelopen 事件来得知连接是否成功建立。

js
let dataChannel = pc.createDataChannel("MyApp Channel");

dataChannel.addEventListener("open", (event) => {
  beginTransmission(dataChannel);
});

手动协商

要手动协商数据通道连接,您首先需要通过 RTCPeerConnection 上的 createDataChannel() 方法创建一个新的 RTCDataChannel 对象,并在选项中指定 negotiated 属性设置为 true。这会向对等连接发出信号,使其不代表您尝试协商通道。

然后,使用 Web 服务器或其他方式带外协商连接。此过程应向远程对等端发出信号,表明它应使用相同的 id 创建自己的 RTCDataChannel,并将 negotiated 属性也设置为 true。这将通过 RTCPeerConnection 连接这两个对象。

js
let dataChannel = pc.createDataChannel("MyApp Channel", {
  negotiated: true,
});

dataChannel.addEventListener("open", (event) => {
  beginTransmission(dataChannel);
});

requestRemoteChannel(dataChannel.id);

在此代码片段中,通道以 negotiated 设置为 true 的方式创建,然后使用一个名为 requestRemoteChannel() 的函数来触发协商,以创建与本地通道具有相同 ID 的远程通道。

这样做可以让您为每个对等端创建具有不同属性的数据通道,并通过使用相同的 id 值来声明性地创建通道。

缓冲

WebRTC 数据通道支持出站数据的缓冲。这是自动处理的。虽然无法控制缓冲区的大小,但您可以了解当前缓冲了多少数据,并且可以选择在缓冲区中的排队数据开始不足时通过事件获得通知。这使得编写高效的例程变得容易,这些例程可以确保总是有数据准备好发送,而不会过度使用内存或完全淹没通道。

了解消息大小限制

您应该保持消息大小适中。虽然大多数现代浏览器支持发送至少 256KB 的消息,但发送大消息存在缺点,尤其是在消息交错不可用时。如果没有消息交错(如 RFC 8260 中定义的那样),在一个数据通道上发送大消息可能会导致 队头阻塞,这反过来又会对其他数据通道上的消息延迟产生负面影响。

最大消息大小可以使用 max-message-size SDP 属性进行协商,该属性在 RFC 8841 中定义。此属性允许每个对等端声明它愿意接收的 SCTP 用户消息的最大大小。通过协商此值,端点可以避免发送大于另一方对等端可以处理的消息。如果 SDP 中不存在 max-message-size 属性,则假定默认值为 64KB。值为 0 表示端点可以处理任何大小的消息,仅受可用内存的限制。

安全

使用 WebRTC 传输的所有数据都经过加密。对于 RTCDataChannel,使用的加密是数据报传输层安全 (DTLS),它基于 传输层安全 (TLS)。由于 TLS 用于保护每个 HTTPS 连接,因此您在数据通道上发送的任何数据都与用户浏览器发送或接收的其他任何数据一样安全。

更根本的是,由于 WebRTC 是两个用户代理之间的点对点连接,数据永远不会通过 Web 或应用程序服务器。这减少了数据被拦截的机会。