在两个浏览器之间发送数据以进行通信、游戏或文件传输可能是一个相当复杂的过程。这需要设置并付费购买用于中继数据的服务器,并且可能需要将其扩展到多个数据中心。在这种情况下,延迟时间可能会很长,并且很难保护数据隐私。
您可以使用 WebRTC 的 RTCDataChannel
API 直接从一个对等方将数据传输到另一个对等方,从而缓解这些问题。本文介绍了如何设置和使用数据渠道的基础知识,以及目前网络上常见的用例。
为何要选择另一个数据渠道?
我们提供了 WebSocket、AJAX 和 服务器发送事件。为什么我们需要另一个沟通渠道?WebSocket 是双向的,但所有这些技术都可以用于与服务器通信。
RTCDataChannel
采用了不同的方法:
- 它与
RTCPeerConnection
API 配合使用,可实现点对点连接。这可以缩短延迟时间,因为没有中间服务器,并且“跳转”次数更少。 RTCDataChannel
使用流控制传输协议 (SCTP),支持可配置的传送语义 - 乱序传送和重传配置。
在桌面设备以及 Android 设备上的 Google Chrome、Opera 和 Firefox 中,RTCDataChannel
现已支持 SCTP。
注意:信令、STUN 和 TURN
WebRTC 支持点对点通信,但仍需要信令服务器来交换媒体和网络元数据,以启动点对点连接。
WebRTC 通过以下方式处理 NAT 和防火墙:
如需详细了解 WebRTC 如何与服务器协同工作以实现信令和网络连接,请参阅现实场景中的 WebRTC:STUN、TURN 和信令。
功能
RTCDataChannel
API 支持一组灵活的数据类型。该 API 旨在完全模仿 WebSocket,RTCDataChannel
支持字符串以及 JavaScript 中的某些二进制类型,例如 Blob、ArrayBuffer 和 ArrayBufferView。在处理文件传输和多人游戏时,这些类型会很有用。
RTCDataChannel
可在不可靠且无序模式(类似于用户数据报协议或 UDP)、可靠且有序模式(类似于传输控制协议或 TCP)以及部分可靠模式下运行:
- 可靠有序模式可保证消息的传输以及传送顺序。这会产生额外的开销,因此可能会导致此模式运行速度变慢。
- 不可靠且无序模式无法保证每封邮件都能送达对方,也无法保证邮件在对方处的传送顺序。这样可以消除开销,让此模式的运行速度更快。
- 部分可靠模式可保证在特定条件(例如重传超时或重传次数上限)下传输消息。消息的排序方式也可以进行配置。
在没有丢包的情况下,前两种模式的性能大致相同。不过,在可靠有序模式下,丢失的数据包会导致其他数据包被阻塞在后面,并且丢失的数据包在重新传输并到达时可能已过时。当然,您可以在同一应用中使用多个数据信道,每个信道都有自己的可靠或不可靠语义。
下面是 Ilya Grigorik 开发的 High Performance Browser Networking 的实用表格:
TCP | UDP | SCTP | |
可靠性 | 可靠 | 不可靠 | 可配置 |
送餐 | 已订购 | 无序 | 可配置 |
传播 | 以字节为导向 | 消息传递 | 消息传递 |
流控制 | 是 | 否 | 是 |
拥塞控制 | 是 | 否 | 是 |
接下来,您将了解如何配置 RTCDataChannel
以使用可靠有序或不可靠无序模式。
配置数据通道
网上有多个 RTCDataChannel
的简单演示:
在这些示例中,浏览器会与自身建立对等连接,然后创建数据通道并通过对等连接发送消息。然后,它会创建数据通道,并通过对等连接发送消息。最后,您的消息会出现在页面另一侧的框中!
使用此测试的起始代码很短:
const peerConnection = new RTCPeerConnection();
// Establish your peer connection using your signaling channel here
const dataChannel =
peerConnection.createDataChannel("myLabel", dataChannelOptions);
dataChannel.onerror = (error) => {
console.log("Data Channel Error:", error);
};
dataChannel.onmessage = (event) => {
console.log("Got Data Channel Message:", event.data);
};
dataChannel.onopen = () => {
dataChannel.send("Hello World!");
};
dataChannel.onclose = () => {
console.log("The Data Channel is Closed");
};
dataChannel
对象是通过已建立的对等连接创建的。此信号可以在发生信号之前或之后创建。然后,传入一个标签来将此渠道与其他渠道区分开来,以及一组可选的配置设置:
const dataChannelOptions = {
ordered: false, // do not guarantee order
maxPacketLifeTime: 3000, // in milliseconds
};
您还可以添加 maxRetransmits
选项(在失败之前重试的次数),但只能指定 maxRetransmits 或 maxPacketLifeTime,不能同时指定二者。对于 UDP 语义,请将 maxRetransmits
设置为 0
,将 ordered
设置为 false
。如需了解详情,请参阅以下 IETF RFC:流控制传输协议和流控制传输协议部分可靠性扩展。
ordered
:数据通道是否应保证有序maxPacketLifeTime
:尝试重新传输失败消息的最长时间maxRetransmits
:尝试重新传输失败消息的最大次数protocol
:允许使用子协议,提供应用的元信息negotiated
:如果设置为 true,则取消在另一对等端上自动设置数据通道,提供您自己的方式在另一端创建具有相同 ID 的数据通道id
:允许您为频道提供自己的 ID,但只能与将negotiated
设置为true
搭配使用
大多数人只需要使用前三个选项:ordered
、maxPacketLifeTime
和 maxRetransmits
。借助 SCTP(现在由所有支持 WebRTC 的浏览器使用),可靠且有序默认为 true。如果您希望从应用层完全控制,则可以使用不可靠且无序的模式,但在大多数情况下,部分可靠性会很有帮助。
请注意,与 WebSocket 一样,RTCDataChannel
会在建立、关闭或出错连接以及收到来自其他对等方的邮件时触发事件。
这样做安全吗?
对于所有 WebRTC 组件而言,加密是必需的。利用 RTCDataChannel
,所有数据都会通过 Datagram Transport Layer Security (DTLS) 进行保护。DTLS 是 SSL 的衍生产品,这意味着您的数据将与使用任何基于 SSL 的标准连接一样安全。DTLS 已标准化,并内置于所有支持 WebRTC 的浏览器中。如需了解详情,请参阅 Wireshark wiki。
改变您对数据的看法
在 JavaScript 中,处理大量数据可能是一个难点。正如 Sharefest 的开发者指出的那样,这需要以新的方式思考数据。如果您要传输的文件大于可用内存量,则必须考虑新的方法来保存此信息。这正是 FileSystem API 等技术大显身手的地方,如您将在下文中看到。
构建文件共享应用
现在,您可以使用 RTCDataChannel
创建可在浏览器中分享文件的 Web 应用。基于 RTCDataChannel
构建意味着传输的文件数据会经过加密处理,不会接触应用提供商的服务器。这项功能加上连接到多个客户端以加快分享速度的可能,使得 WebRTC 文件分享成为网络的绝佳候选方案。
成功转移需要完成以下几步:
- 使用 File API 在 JavaScript 中读取文件。
- 使用
RTCPeerConnection
在客户端之间建立对等连接。 - 使用
RTCDataChannel
在客户端之间创建数据通道。
尝试通过 RTCDataChannel
发送文件时,需要考虑以下几点:
- 文件大小:如果文件大小较小,并且可以作为一个 Blob 进行存储和加载,您可以使用 File API 加载到内存中,然后原封不动地通过可靠的通道发送文件(不过请注意,浏览器对最大传输大小施加了限制)。随着文件大小的增加,事情变得更加复杂。当需要分块机制时,系统会加载文件块并将其发送到其他对等方,同时附带
chunkID
元数据,以便对等方能够识别它们。请注意,在这种情况下,您还需要先将分块保存到离线存储空间(例如,使用 FileSystem API),并仅在拥有完整文件时将其保存到用户的磁盘。 - 分块大小:这是应用数据的最小“原子”。由于目前存在发送大小限制,因此必须进行分块(不过,这将在未来版本的数据通道中得到修正)。目前建议的最大分块大小为 64KiB。
文件完全传输到另一端后,您可以使用锚点标记下载该文件:
function saveFile(blob) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'File Name';
link.click();
};
PubShare 和 GitHub 上的这些文件共享应用就使用了此技术。它们都是开源的,为基于 RTCDataChannel
的文件共享应用提供了良好的基础。
那么,您可以做些什么?
RTCDataChannel
开启了构建文件共享、多人游戏和内容分发应用的新方式。
- 如前所述进行点对点文件共享
- 多人游戏与 WebGL 等其他技术搭配使用,如 Mozilla 的 BananaBread 中所示
- PeerCDN 对内容传送进行了重新构想,该框架通过点对点数据通信传送 Web 资源
改变应用构建方式
现在,您可以通过 RTCDataChannel
使用高性能、低延迟的连接,从而提供更具吸引力的应用。PeerJS 和 PubNub WebRTC SDK 等框架可简化 RTCDataChannel
的实现,该 API 现已在各个平台上获得广泛支持。
RTCDataChannel
的出现可能会改变您对浏览器中数据传输的看法。