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

文 / Philipp Hancke

译 / 元宝,咪宝

审校 / 王盛

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

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

我们来做一个简单的单页示例测试一下,类似于传输文本的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关于这个话题的介绍,这段视频已经有几年的历史了,但是它提供了一些额外的背景知识:

视频网址: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并提供反馈。

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

QUIC DataChannels的第一步相关推荐

  1. 使用myeclipse的第一步

    使用myeclipse的第一步 将以下代码copy放在一个包中运行,然后在控制台输入任意字符,回车,然后控制台打印一串密匙,这里你输入的就是账号,控制台返回的就是注册码,点击MyEclipse-> ...

  2. python安装包_迈出Python学习第一步:Python开发环境的下载与安装

    所谓"磨刀不误砍柴工"."工欲善其事,必先利其器",都在告诉我们一个道理:要做好一个事情,事先做好充分的准备工作是非常重要的.所以在我们正式学习用Python编 ...

  3. ecshop入门第一步,替换ecshop模板的显示图片

    所有的都是模范默认模板来制作,所以应该参考默认模板的一些数据设置 1.找到themes\default\images文件夹下 screenshot.png 图片 默认如下: 在你的模板文件夹下新建一个 ...

  4. python采集第一步

    2019独角兽企业重金招聘Python工程师标准>>> 上次说要做一个http://www.m4493.com/的美女站点,需要使用python进行数据采集 接下来我们就开始采集数据 ...

  5. 初学架构设计的第一步:需求、愿景与架构

    初学架构设计的第一步:需求.愿景与架构 了解<需求>.<愿景>与<架构>三者的关系.也就是<需求分析>.<观想愿景>与<架构设计> ...

  6. 使用html测试数据库连接与操作(含界面) 第一步界面设计

    前面写的那篇文章,只是实现了页面刷新就读取数据库的过程,还不能有人工干预,还不像一个正式的东东,这可能和我以前写c#养成的习惯似的,总想弄的完美点,第一步先吧界面弄出来,说实话,具体怎么通过按钮出发p ...

  7. php内容采集系统,第一步、采集规则

    采集第一步工作是设置目标网站的采集规则 先确定采集哪一个目标网站,我们用 腾讯科技频道为例:http://tech.qq.com/all/newtech.htm 一.列表采集规则 1.设置采集规则和编 ...

  8. 程序员失业第一步?斯坦福研究员用AI从编译器反馈中学习改Bug

    来源:AI科技评论 本文约2700字,建议阅读10分钟 本文介绍了来自斯坦福大学的两位研究员研究了如何使用AI来自动修复程序,以期未来程序修复自动化可以大大提高编程和学习编程的效率. 众所周知,程序员 ...

  9. SAP WM LT15不能取消二步法确认场景中只做过第一步确认的TO单

    SAP WM LT15不能取消二步法确认场景中只做过第一步确认的TO单 1,如下TO 需要2步法确认,TO#3000006418 看其确认状态时黄色三角形状态,说明第一步确认(LT1D)已经被业务人员 ...

最新文章

  1. Matlab与线性代数 -- 矩阵的重组2
  2. 手机版的python-python手机版
  3. Python 计算机视觉(三)—— 数字图像处理基本操作
  4. boost::locale::utf8_codecvt用法的测试程序
  5. IntelliJ IDEA中日志分类显示设置
  6. matlab程序聚类预测机器学习
  7. Python while循环 - Python零基础入门教程
  8. 感恩有您!《大数据》祝您新年快乐!
  9. python制作的游戏如何转化为swf_如何从python生成swf格式的幻灯片?
  10. 使用VSTS为ASP.NET Core构建DevOps CI/CD管道
  11. Android学习笔记---监听ContentProvider(内容共享者)中数据的变化
  12. redis 启动无输出_Git Bash 中执行交互式命令无响应
  13. PL/SQL相关的数据字典
  14. eclipse html清理缓存,eclipse中的缓存怎么清理
  15. 数据结构 创建结构体学生表 c语言
  16. CSS3的癫疯展示——3D立方体动画(你要的全景视图来了)
  17. 2017年国赛H题_远程幅频特性测试装置训练总结(硬件部分)
  18. 【youcans 的 OpenCV 例程200篇】176.图像分割之均值漂移算法 Mean Shift
  19. php爬取房源,Python 爬虫 链家二手房(自行输入城市爬取)
  20. WideResNet(宽残差网络)介绍与代码

热门文章

  1. 【转】qqface使用实例
  2. 中国移动2016年Web应用防火墙集采:绿盟、深信服中标
  3. 环美亚二十年装修师傅分享,甲醛的八种来源
  4. CentOS6配置部署Zabbix监控
  5. 外包女程序员-----励志段子 留着 等没事的时候看看
  6. Android的手势交互
  7. CSS布局最常用属性float(浮动)和position(定位)
  8. 传对象与传串_简单介绍
  9. Gym - 101471D Money for Nothing(决策单调性+分治+贪心)
  10. 2020CCPC(长春) - Strange Memory(树上启发式合并+位运算)