WebRTC搭建前端视频聊天室——数据通道篇
本文翻译自WebRTC data channels
在两个浏览器中,为聊天、游戏、或是文件传输等需求发送信息是十分复杂的。通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成多个数据中心。这种情况下很容易出现很高的延迟,同时难以保证数据的私密性。
这些问题可以通过WebRTC提供的RTCDataChannel API来解决,他能直接在点对点之间传输数据。这篇文章将介绍如何创建并使用数据通道,并提供了一些网络上常见的用例
为了充分理解这篇文章,你可能需要去了解一些RTCPeerConnection API的相关知识,以及STUN,TURN、信道如何工作。强烈推荐Getting Started With WebRTC这篇文章
为什么我们需要另外一个数据通道
我们已经有WebSocket、AJAX和服务器发送事件了,为什么我们需要另外一个通信信道?WebSocket是全双工的,但这些技术的设计都是让浏览器与服务器之间进行通信。
RTCDataChannel则是一个完全不同的途径:
- 它通过RTCPeerConnection API,可以建立点对点互联。由于不需要中介服务器,中间的“跳数”减少,延迟更低。
- RTCDataChannel使用Stream Control Transmission Protocol(SCTP)协议,允许我们配置传递语义:我们可以配置包传输的顺序并提供重传时的一些配置。
基于SCTP的支持的RTCDataChannel已经能够在桌面的Chrome、Opera和Firefox中使用,移动端则有Android支持。
一个警告:信令、STUN和TURN
尽管WebRTC允许点对点的通信,但它依然需要服务器:
* 信令传输:建立点对点的连接需要传输一些媒体和网络相关的元数据信息,需要通过服务器
* NAT和防火墙穿透:我们需要通过ICE框架来建立点与点之间的网络路径。可以使用STUN服务器(确定双方的可公开访问你的IP地址和端口)以及TURN服务器(如果直接连接失败,就必须数据中继了)
WebRTC in the real world: STUN, TURN, and signaling 文章详细介绍了WebRTC如何与这两种服务器进行交互
功能
RTCDataChannel API支持灵活的数据类型。它的API是模仿WebSocket设计的,并且支持JavaScript中的二进制类型如Blob、ArrayBuffer和ArrayBufferView,另外还支持字符串。这些类型对于文件传输和多玩家的游戏来说意义重大。
以上来自Ilya Grigorik的High Performance Browser Networking
RTCDataChannel在不可靠模式(类似于UDP)或可靠模式(类似于TCP)下都能够正常工作。但这两种模式有一些不同:
- 可靠模式:保证消息传输一定成功,并保证按序到达。这自然需要一定量的开销,速度也更慢
- 不可靠模式:不保证消息传输一定成功,也不保证按序到达。这消除了那些开销,速度也更快
在不会丢包的情况下,这两种模式的效率差不多。然而,可靠模式下,丢包将造成后续的所有包阻塞,丢失的数据包也将重传直至其成功到达。当然,我们能在同一个应用中使用多个数据通道,每一个有他们自己的可靠性
下面将说明如何去配置可靠模式或不可靠模式的RTCDataChannel
配置数据通道
网上已经有很多RTCDataChannel的例子了:
ps:PubBub是一个实时信息通讯应用开发公司
在这个例子中,浏览器创建了一个对等连接连接到自己。然后在这个对等连接n上创建了一个数据通道,发送了一些消息。最后,消息成功抵达并显示在页面上。
var peerConnection = new RTCPeerConnection(); //使用信令传输信道创建对等连接 var dataChannel = peerConnection.createDataChannel("myLabel", dataChannelOptions); dataChannel.onerror = function (error) { console.log("Data Channel Error:", error); }; dataChannel.onmessage = function (event) { console.log("Got Data Channel Message:", event.data); }; dataChannel.onopen = function () { dataChannel.send("Hello World!"); }; dataChannel.onclose = function () { console.log("The Data Channel is Closed"); };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
dataChannel对象建立在一个已经创建完毕的对等连接之上。它可以创建在信令传输前后。另外,可以赋予一个label来作区分,并提供一系列的配置选项:
var dataChannelOptions = { ordered: false, //不保证到达顺序 maxRetransmitTime: 3000, //最大重传时间 };
- 1
- 2
- 3
- 4
- 5
我们可以加入一个maxRetransimits选项(最大重传次数),但maxRetransimitTime或maxRetransimits只能设定一个,不能两个懂事设定。如果想使用UDP的方式,设定maxRetransmits为0,ordered为false。如果想要获取更多信息,请查看RFC 4960(SCTP)和RFC 3758(SCTP部分可靠性)
- ordered: 数据通道是否保证按序传输数据
- maxRetrasmitTime:在信息失败前的最大重传时间(强迫进入不可靠模式)
- maxRetransmits:在信息失败前的最大重传次数(强迫进入不可靠模式)
- protocol:允许使用一个自协议,但如果协议不支持,将会失败
- negotiated:如果设为true,将一处对方的数据通道的自动设置,也就是说,将使用相同的id以自己配置的方式与对方建立数据通道
- id:为数据通道提供一个自己定义的ID
它安全吗?
在WebRTC所有的组件中,都会强制进行加密。在RTCDataChannel中,所有的数据都使用数据报传输层安全性(DTLS)。DTLS是SSL的衍生,也就是说,你的数据将和使用基于SSL的连接一样安全。DTLS已经被标准化,并内置于所有支持WebRTC的浏览器中。如果需要更多关于DTLS信息,请访问Wireshark的维基
改变你考虑数据的方式
处理大批量的数据,一直是JavaScript的一个难点。正如Sharefest所提出的观点,我们需要用一种新的方式来考虑数据。如果你需要传输一个比你当前可用内存更大的文件,就必须考虑新的保存信息的方式了。这也就是像FileSystem API等技术存在的意义。我们将在下面进行介绍
搭建一个文件共享应用
现在我们可以通过RTCDataChannel来创建文件共享应用。将应用建立在RTCDataChannel智商也意味着传输的文件数据都将加密,而且不会经过应用的服务器端。通过这个功能,我们能够实现多用户之间的互联,进行文件共享。
需要成功传输一个文件,我们需要如下几步:
1. 通过JavaScript的File API读取文件数据
2. 使用RTCPeerConnection在用户间创建一个对等连接
3. 使用RTCDataChannel在用户间创建一个数据通道
在使用RTCDataChannel时,还有一些其他问题需要考虑:
- 文件大小:如果文件很小,能够直接通过一个Blob进行存储和读取,那么我们可以直接使用File API将其读进内存,并通过可靠的数据通道发送(但是需要注意的是,浏览器有最大传输大小的限制)。随着文件变大的话,就不那么简单了。我们需要一个分块机制:文件将分成多个碎片,称为文件块。我们不再直接发送整个文件,而是一次发送一个文件块。当然文件块上会有一些元数据如块的ID,方便对方能够识别。接收到文件块之后,首先将这些文件块保存在离线存储中(例如,使用FileSystem API),只有当所有块都接收完毕,才将其拼合起来成为完整的文件,保存到用户的硬盘。
- 速度:文件传输更适合使用可靠模式(像TCP)还是非可靠模式(像UDP)还有待商榷。如果应用知识简单的一对一文件传输,使用不可靠的数据通道将需要设计一定的响应/重传协议。你必须自己来实现它,就算你非常优秀,它仍然不会比使用可靠的数据传输快多少。可靠而无序的数据通道将会更加合适,但是如果是多方文件传输,结果可能会有所不同。
- 块大小:这些是你的应用中的最小的“原子”数据。目前有传输大小限制(尽管以后可能不会有限制),所以必须要进行分块。目前建议的最大块大小为16KB。
如果文件已经被完全传输,就可以使用一个a标签提供下载了:
function saveFile(blob) { var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = 'File Name'; link.click(); };
- 1
- 2
- 3
- 4
- 5
- 6
目前已经有两个文件共享的应用使用了这种方式:pubnub.github.io/rtc-pubnub-fileshare和github.com/Peer5/ShareFest,这两个应用都是开源的,并提供了基于RTCDataChannel的文件共享
那么我们能做什么?
RTCDataChannel为文件共享、多人游戏以及内容交付应用提供了全新的实现思路:
* 上面已经提到了点对点的文件传输了
* 多人游戏,与诸如WebGL等其他技术相结合,比如Mozilla的Banana Bread
* 内容交付:由PeerCDN重新改造的一个用于提供点对点通信提供资源的框架
改变你构建应用的方式
现在我们可使用高新能、低延迟的RTCDataChannel来创建更优秀的应用了。一些框架,诸如PeerJS和PubNub WebRTC SDK,使得RTCDataChannel更加易于使用,其API也被各个平台所支持
RTCDataChannel所带来的优势能够改变你在浏览器中传输数据的观念。
更多资讯
- Getting started with WebRTC
- WebRTC in the real world: STUN, TURN and signaling
- WebRTC resources
- W3C Working Draft
- IETF WebRTC Data Channel Protocol Draft
- How to send a File Using WebRTC Data API
- 7 Creative Uses of WebRTC’s Data Channel
- Banana Bread 3D first person shooter game compiled to JS+WebGL, - - using WebRTC data channels in multiplayer mode
WebRTC搭建前端视频聊天室——数据通道篇的更多相关文章
- 使用WebRTC搭建前端视频聊天室——数据通道篇
本文翻译自WebRTC data channels 在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成 ...
- 使用WebRTC搭建前端视频聊天室——点对点通信篇
WebRTC给我们带来了浏览器中的视频.音频聊天体验.但个人认为,它最实用的特性莫过于DataChannel——在浏览器之间建立一个点对点的数据通道.在DataChannel之前,浏览器到浏览器的数据 ...
- 使用WebRTC搭建前端视频聊天室——信令篇
博客原文地址 建议看这篇之前先看一下使用WebRTC搭建前端视频聊天室——入门篇 如果需要搭建实例的话可以参照SkyRTC-demo:github地址 其中使用了两个库:SkyRTC(github地址 ...
- 使用WebRTC搭建前端视频聊天室——入门篇
http://segmentfault.com/a/1190000000436544 什么是WebRTC? 众所周知,浏览器本身不支持相互之间直接建立信道进行通信,都是通过服务器进行中转.比如现在有两 ...
- WebRTC搭建前端视频聊天室——信令篇
这篇文章讲述了WebRTC中所涉及的信令交换以及聊天室中的信令交换,主要内容来自WebRTC in the real world: STUN, TURN and signaling,我在这里提取出的一 ...
- 使用WebRTC搭建前端视频聊天室
在两个浏览器中,为聊天.游戏.或是文件传输等需求发送信息是十分复杂的.通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成多个数据中心.这种情况下很容易出现很高的延迟,同时难 ...
- WebRTC实现网页版多人视频聊天室
因为产品中要加入网页中网络会议的功能,这几天都在倒腾 WebRTC,现在分享下工作成果. 话说 WebRTC Real Time Communication 简称 RTC,是谷歌若干年前收购的一项技术 ...
- 玩转Node.js(四)-搭建简单的聊天室
玩转Node.js(四)-搭建简单的聊天室 Nodejs好久没有跟进了,最近想用它搞一个聊天室,然后便偶遇了socket.io这个东东,说是可以用它来简单的实现实时双向的基于事件的通讯机制.我便看了一 ...
- 开源Flex Air版免费激情美女视频聊天室,免费网络远程视频会议系统((Flex,Fms3联合打造))
开源Flex Air版免费激情美女视频聊天室,免费网络远程视频会议系统((Flex,Fms3联合打造)) Flex,Fms3系列文章导航 Flex,Fms3相关文章索引 本篇是视频聊天,会议开发实 ...
随机推荐
- 揭秘MySQL主从数据不一致
前言: 目前MySQL数据库最常用的是主从架构,大多数高可用架构也是通过主从架构演变而来.但是主从架构运行时间长久后容易出现数据不一致的情况,比如因从库可写造成的误操作或者复制bug等,本篇文章将会详 ...
- yaml文件配置logger
yaml 今天用yaml文件写了一下logging的配置,文件如下: version: 1 disable_existing_loggers: False formatters: simple: fo ...
- Plan B
王兴曾经说过: 2019 年是过去 10 年中最差的一年,也是未来 10 年中最好的一年. 之前我希望王兴预判错了,但现在我发现这位掌控着生活消费类数据的大佬应该不是扯淡. 今年的内部和外部环境真的很 ...
- SHOI2017 分手是祝愿
分手是祝愿 有
- 【时空大数据】Access 到 Postgres 数据迁移遇到的ODBC坑----驱动程序和应用程序之间的体系结构不匹配
1.安装Postgres10 2.安装Postgis插件 3.创建数据库 4.执行postgis脚本插件:参考https://www.cnblogs.com/defineconst/p/1064853 ...
- Game-Based Learning Is Changing How We Teach. Here's Why.
https://www.edsurge.com/news/2019-02-04-game-based-learning-is-changing-how-we-teach-here-s-why This ...
- 没有内置小鹤双拼的rime输入法就是差劲
没有内置小鹤双拼的rime输入法就是差劲,还特立独行,搞什么繁体~ 没有内置小鹤双拼的rime输入法就是差劲,还特立独行,搞什么繁体~ 没有内置小鹤双拼的rime输入法就是差劲,还特立独行,搞什么繁体 ...
- list数组排序 Collections 按Date时间降序排列
@ResponseBody @RequestMapping(value = {"K12", "12"}) public String refurbishLigh ...
- 浏览器渲染详细过程:重绘、重排和 composite 只是冰山一角
https://juejin.im/entry/590801780ce46300617c89b8 渲染 这张很经典的图许多人都看过,其中的概念大家应该都很熟悉,也就是这么几个步骤:js修改dom结构或 ...
- scala 学习笔记--集合
1.scala集合的null 是nil 而不是null 2.set的三个方法union,intersect,diff union--合并去重 intersect--交集 diff--a减去(a和b交集 ...