基于QUIC的数据通道被认为是当前SCTP传输的替代方案。 Google WebRTC工作组已经在对其进行试验:
让我们也尝试一下。 为此,我们将创建一个
类似于WebRTC通道示例的单页应用程序
以进行文本传输 -这是一个完全正常的示例(没有信令服务器),此外,这将使比较实现WebRTC DataChannel的方法变得容易。
在开始之前,让我们回顾一下
DataChannel的基础。
简要介绍DataChannel
WebRTC的DataChannel允许参与者交换任意数据。 它们既可以可靠(在传输文件时非常有用),又可以不可靠(对于游戏中的位置信息是可以接受的)。 该API是
RTCPeerConnection
的扩展,如下所示:
const dc = pc.createDataChannel("some label string");
在WebRTC官方样本页面上,有
发送字符串和
二进制数据的示例。
DataChannel使用
SCTP 。 它与RTP传输并行处理音频和视频流。 与音频和视频流通常使用的UDP不同,SCTP提供了许多其他功能,例如通过单个连接的多路复用通道或可靠,部分可靠(即可靠但无序)和不可靠的模式。
Google于2012年推出了QUIC(有关协议历史记录及其细微差别的更多信息,请参见
我们的其他材料 -译者注)。 像WebRTC一样,QUIC协议也已在IETF的支持下采用,现在为
HTTP / 3 。 QUIC具有许多重大创新,例如:减少延迟,基于拥塞控制的带宽计算,直接延迟校正(FEC)以及在用户空间(而非内核)中的实现以实现更快滚动。
QUIC可以替代WebRTC的RTCP,例如DataChannel的传输。 当前的实验试图通过使用单独版本的ICE传输来避免使用RTCPeerConnection API(
和SDP! )。 将其视为虚拟连接,可以增加安全性和
NAT遍历 。
在下面的视频中,Chrome网络团队的Ian Swett解释了这个概念。 尽管此演讲已有多年历史,但仍提供有关该主题的其他信息:
QUIC的第一步
幸运的是,
2015年文章中的大多数
代码仍然适用,并且可以轻松适应新的API。 让我们弄清楚。
从这里克隆代码或
在这里尝试。 请注意,Chrome(必须为73+版本,现在是Canary版本)必须运行特殊标志才能在本地运行该实验:
google-chrome-unstable --enable-blink-features=RTCQuicTransport,RTCIceTransportExtension
ICE传输设置
RTCIceTransport规范基于ORTC,因此其设置类似于旧代码:
const ice1 = new RTCIceTransport(); ice1.onstatechange = function() { console.log('ICE transport 1 state change', ice1.state); }; const ice2 = new RTCIceTransport(); ice2.onstatechange = function() { console.log('ICE transport 2 state change', ice2.state); };
请注意,与ORTC不同,此API没有RTCIceGatherer。 因为我们已经拥有安装ICE传输所需的一切。
配置QUIC传输
const quic1 = new RTCQuicTransport(ice1); quic1.onstatechange = function() { console.log('QUIC transport 1 state change', quic1.state); }; const quic2 = new RTCQuicTransport(ice2); quic2.onstatechange = function() { console.log('QUIC transport 2 state change', quic2.state); };
在这里,实验脱离了使用基于证书的身份验证的规范。 而是使用公共密钥,
如Google Developers帖子所述 :
RTCQuicTransport连接配置有API公钥。 我们目前不打算使用此API代替原始验证。 当QUIC开始在Chromium中支持此证书时,它将由远程证书信令代替以验证自签名证书。
到目前为止,一切都很好。
QUICStream用于发送和接收数据
使用QUICStream比WebRTC DataChannel有点棘手。 WHATWG工作组创建的Streams API(
请参阅有关MDN的详细信息 )已被
接受,但尚未实现 。
我们仅在QUIC传输进入“已连接”状态后才创建
sendStream
在不同的状态下会导致错误:
quic1.onstatechange = function() { console.log('QUIC transport 1 state change', quic1.state); if (quic1.state === 'connected' && !sendStream) { sendStream = quic1.createStream('webrtchacks');
然后,将处理程序附加到“提交”按钮和输入字段:单击按钮后,来自输入字段的文本在
Uint8Array中进行编码并写入流中:
document.getElementById('sendButton').onclick = () => { const rawData = document.getElementById('dataChannelSend').value; document.getElementById('dataChannelSend').value = '';
第一个条目将触发远程QUIC传输上的
onquicstream
事件:
...然后我们等待数据可读:
function ondata() { const buffer = new Uint8Array(receiveStream.readBufferedAmount); const res = receiveStream.readInto(buffer); const data = decoder.decode(buffer); document.getElementById('dataChannelReceive').value = data; receiveStream.waitForReadable(1) .then(ondata); }
来自
receiveStream
所有数据将被读取,解码为文本并放置在输出字段中。 因此,每次出现可读数据时。
结论与评论
我希望这个例子比
Google博客上的类似例子更容易理解。 这种方法几乎不适合P2P连接,SCTP上的DataChannel已经对它们很好。 但是,这可能是另一端使用QUIC服务器的Web套接字的有趣替代方案。 在此之前,您应该确定一种使用不可靠且混乱的渠道的不错方法。 我认为,上述文章中的建议看起来更像是骇客,而不是决策。
还不清楚开发人员正在等待外界的反馈。 “已经介绍了规范,而不是再次雕刻快捷方式,而这些快捷方式将在我们身上保留数年,”听起来太明显了。 另外,社区的普遍意见倾向于使用WHATWG流,这使开发人员感到奇怪,他们要求测试自己的API来读取数据。
我还希望Chromium中的SCTP具有其他功能。 例如,
关于DataChannel的查询 -顺便说一句,评分最高-三年来几乎没有触及。 目前尚不清楚,当仍有SCTP任务时,为什么要重点关注QUIC。 但是,这不应阻止任何人测试QUIC和结果反馈。
Voximplant的评论
告诉我们
前端irbisadm :
长期以来,我们的SDK已用于向网络套接字发送信号。 这是一个出色的,经过时间考验的标准,但是存在一些问题。 第一个是TCP。 TCP在移动网络上不是那么好和快速,而且它不支持网络之间的漫游。 其次,它通常是文本形式的(也有二进制模式,但是您很少看到它)。
我们最近在DataChannel上启动了信号协议的封闭beta测试。 该协议也不是没有缺点,但是由于它可以在较差的网络中工作并且在漫游时可以一见钟情。 您更改过网络吗? 无需重新创建连接。 在大多数情况下, ICE Restart
将有助于找到一种新的通信方式。 但是,正如我所说,该协议仍然存在缺陷:并非所有浏览器都支持所有协议扩展,例如保证交付和数据包顺序支持; 协议也不支持开箱即用的文本模式的gzip。 但是所有这些问题都可以在应用程序端解决。