QUIC DataChannels的第一步

640?wx_fmt=png


对于WebRTC,QUIC协议可能提供SCTP之外的替代方案作为DataChannel的传输方式,本文通过示例测试的方式将该方法与WebRTC DataChannels进行了比较。LiveVideoStack对文章内容进行了翻译。感谢bilibili高级工程师王盛提供的审校支持。


文 / Philipp Hancke

译 / 元宝,咪宝

审校 / 王盛

原文 https://webrtchacks.com/first-steps-with-quic-datachannel/


基于QUIC的DataChannels现在被视为基于SCTP传输的替代方案。谷歌的WebRTC工作人员正在对其进行实验:


640?wx_fmt=png


我们来做一个简单的单页示例测试一下,类似于传输文本的WebRTC数据通道示例(https://webrtc.github.io/samples/src/content/datachannel/basic/)。它提供了一个完整的工作示例,不涉及信令服务器,还允许更容易地将该方法与WebRTC DataChannels进行比较。


在看实际代码之前,首先让我们回顾一下DataChannel的一些基础知识。


快速回顾DataChannel 


WebRTC中的DataChannel允许在对等点之间交换任意数据。它们既可以是可靠的,对于文件传输之类的事情非常有用,也可以是不可靠的,例如可以用于在游戏中交换位置信息。这个API是WebRTC里RTCPeerConnection的扩展,如下图所示:


 
 

const dc = pc.createDataChannel("some label string");
// wait for this to be open, e.g. by adding an event listener, then call send
dc.send("some string");

// on the other side
otherPc.addEventListener('datachannel', e => {
  const channel = e.channel;
  channel.onmessage = event => {
    console.log('received', event.data);
  });
});


WebRTC示例页面提供了一些用于发送简单字符串(https://webrtc.github.io/samples/src/content/datachannel/basic/)以及二进制数据(如arraybuffers)的示例。

(https://webrtc.github.io/samples/src/content/datachannel/datatransfer/)


DataChannel使用一种称为SCTP的协议。它与用于语音和视频流的基于RTP的传输并行运行。与通常使用UDP传输语音和视频流不同,SCTP提供各种特性,例如在同一连接上多路复用多个信道,以及提供可靠、部分可靠(即可靠但无序)和不可靠的模式。


谷歌在2012年推出了QUIC。就像它对WebRTC的做法一样,它后来把QUIC带到了IETF,现在是HTTP/3,QUIC提供了许多出色的功能,包括减少延迟、基于带宽估计的拥塞控制、前向纠错(FEC)以及在用户空间比内核中实现更快的部署周期。


对于WebRTC,QUIC协议可能提供SCTP之外的替代方案作为DataChannel的传输方式。此外,当前的实验还试图避免使用RTCPeerConnection API(和SDP!(https://webrtchacks.com/webrtc-sdp-inaki-baz-castillo/)),使用独立版本的ICE传输。我们可以把它想象成一个虚拟连接,它增加了一些安全性和一堆的NAT遍历(https://webrtchacks.com/stun-helps-webrtc-traverse-nats/)


下面这段来自WebRTC Boston的视频是Chrome网络团队的Ian Swett关于这个话题的介绍,这段视频已经有几年的历史了,但是它提供了一些额外的背景知识:

 

640?wx_fmt=png


视频网址:https://youtu.be/mIvyOFu1c1Q


QUIC的第一步


幸运的是, 2015年发布的“使用ORTC的第一步(https://webrtchacks.com/first-steps-ortc/)文章中的大部分代码仍然是具有相关性的,并且可以快速适应这个新的API。


复制代码(https://github.com/webrtchacks/first-steps-ortc)尝试一下(https://webrtchacks.github.io/first-steps-ortc/quic.html)。请注意,需要使用特殊的标志来启动Chrome(当前为Canary的73+)才能在本地进行实验:


 
 

google-chrome-unstable --enable-blink-features=RTCQuicTransport,RTCIceTransportExtension


设置ICE传输


这个RTCIceTransport 规范(https://github.com/w3c/webrtc-ice)是以ORTC为模型的,因此建立ICE transport与我们已有的旧代码非常相似:

 

 
 

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);
};
// Exchange ICE candidates.
ice1.onicecandidate = function(evt{
    console.log('1 -> 2', evt.candidate);
    if (evt.candidate) {
        ice2.addRemoteCandidate(evt.candidate);
    }
};
ice2.onicecandidate = function(evt{
    console.log('2 -> 1', evt.candidate);
    if (evt.candidate) {
        ice1.addRemoteCandidate(evt.candidate);
    }
};

// Start the ICE transports.
ice1.start(ice2.getLocalParameters(), 'controlling');
ice2.start(ice1.getLocalParameters(), 'controlled');
ice1.gather(iceOptions);
ice2.gather(iceOptions);



与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);
};

// Add an event listener for the QUIC stream.
quic2.addEventListener('quicstream', (e) => {
    console.log('QUIC transport 2 got a stream', e.stream);
    receiveStream = e.stream;
});



在这一点上,实验偏离了使用证书指纹的规范https://w3c.github.io/webrtc-quic/)。相反,在原始博客文章的注释中指出了PSK密钥:


注意:RTCQuicTransport连接使用PSK密钥API进行设置。我们目前不打算将此API保留在原始审判之前。一旦将此支持添加到Chromium中的QUIC,它将被信令远程证书指纹替换,以验证握手中使用的自签名证书。


到现在为止还挺好的。


使用QUICStream发送和接收数据


使用QUICStream比使用WebRTC DataChannel稍微要复杂一点。WHATWG流API(请在MDN上阅读更多关于它的信息(https://developer.mozilla.org/en-US/docs/Web/API/Streams_API))被考虑过,但没有实现(https://github.com/w3c/webrtc-quic/issues/2)


我们在QUIC传输连接起来时才创建 sendStream,因为它在此之前会出错:

 

 
 

quic1.onstatechange = function({
  console.log('QUIC transport 1 state change', quic1.state);
  if (quic1.state === 'connected' && !sendStream) {
    sendStream = quic1.createStream('webrtchacks'); // similar to createDataChannel.
    document.getElementById('sendButton').disabled = false;
    document.getElementById('dataChannelSend').disabled = false;
  }
};



并启用发送按钮和输入文本区域。单击发送按钮后,文本将从文本区域中抓取,以Uint8Array编码写入sendStream中:


 
 

document.getElementById('sendButton').onclick = () => {
    const rawData = document.getElementById('dataChannelSend').value;
    document.getElementById('dataChannelSend').value = '';
    // we need a Uint8Array. Fortunately text is easy to convert using TextEncoder.
    const data = encoder.encode(rawData);
    sendStream.write({
        data,
    });
};


第一次写入将触发远程QUICTransport上的onquicstream事件:

 

 
 

// Add an event listener for the QUIC stream.
quic2.addEventListener('quicstream', (e) => {
    console.log('QUIC transport 2 got a stream', e.stream);
    receiveStream = e.stream;
    receiveStream.waitForReadable(1)
        .then(ondata);
});



我们将等待数据可以读取:


 
 

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博客文章中(https://developers.google.com/web/updates/2019/01/rtcquictransport-api)提供的示例更容易理解和修改。客户端到客户端的连接很难成为这里的主要用例——基于SCTP的DataChannel已经很好地介绍了这一点。但是,这可能成为WebSockets的另一种有趣的替代方案,在另一端使用基于QUIC的服务器。在此之前,需要定义一种表示不可靠和无序通道的好方法。在我看来,博客文章中的建议非常像黑客。


除此之外,我还不清楚团队正在寻找什么样的外部反馈。“实施规范而不是再次采取持续多年的捷径”是相当明显的。此外,社区团体现在的共识似乎是使用WHATWG流,这使得开发人员测试自己开发的API来处理读取变得更加奇怪。


我也希望Chromium的SCTP能有一些额外的功能。例如,这个DataChannel请求最高级的Chromium原生问题为什么在三年内几乎没有改变。我不太明白为什么在SCTP上有工作要做的时候,要关注QUIC,但这不应该阻止任何人测试QUIC并提供反馈。



640?wx_fmt=jpeg


点击【阅读原文】或扫描图中二维码了解更多LiveVideoStackCon 2019 上海 音视频技术大会 讲师信息。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值