使用WebRTC搭建前端视频聊天室——数据通道篇

本文翻译自WebRTC data channels

在两个浏览器中,为聊天、游戏、或是文件传输等需求发送信息是十分复杂的。通常情况下,我们需要建立一台服务器来转发数据,当然规模比较大的情况下,会扩展成多个数据中心。这种情况下很容易出现很高的延迟,同时难以保证数据的私密性。

这些问题可以通过WebRTC提供的RTCDataChannel API来解决,他能直接在点对点之间传输数据。这篇文章将介绍如何创建并使用数据通道,并提供了一些网络上常见的用例

为了充分理解这篇文章,你可能需要去了解一些RTCPeerConnection API的相关知识,以及STUN,TURN、信道如何工作。强烈推荐Getting Started With WebRTC这篇文章

为什么我们需要另外一个数据通道

我们已经有WebSocketAJAX服务器发送事件了,为什么我们需要另外一个通信信道?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,另外还支持字符串。这些类型对于文件传输和多玩家的游戏来说意义重大。

[图片上传失败...(image-813875-1513063558572)]

以上来自Ilya GrigorikHigh Performance Browser Networking

RTCDataChannel在不可靠模式(类似于UDP)或可靠模式(类似于TCP)下都能够正常工作。但这两种模式有一些不同:

  • 可靠模式:保证消息传输一定成功,并保证按序到达。这自然需要一定量的开销,速度也更慢
  • 不可靠模式:不保证消息传输一定成功,也不保证按序到达。这消除了那些开销,速度也更快

在不会丢包的情况下,这两种模式的效率差不多。然而,可靠模式下,丢包将造成后续的所有包阻塞,丢失的数据包也将重传直至其成功到达。当然,我们能在同一个应用中使用多个数据通道,每一个有他们自己的可靠性

下面将说明如何去配置可靠模式或不可靠模式的RTCDataChannel

配置数据通道

网上已经有很多RTCDataChannel的例子了:

simpl.info/dc

googlechrome.github.io/webrtc/dc1.html(SCTP或者RTP)

pubnub.github.io/webrtc(两个PubNub用户)

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

dataChannel对象建立在一个已经创建完毕的对等连接之上。它可以创建在信令传输前后。另外,可以赋予一个label来作区分,并提供一系列的配置选项:

var dataChannelOptions = {
  ordered: false, //不保证到达顺序
  maxRetransmitTime: 3000, //最大重传时间
};

我们可以加入一个maxRetransimits选项(最大重传次数),但maxRetransimitTimemaxRetransimits只能设定一个,不能两个懂事设定。如果想使用UDP的方式,设定maxRetransmits为0,orderedfalse。如果想要获取更多信息,请查看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智商也意味着传输的文件数据都将加密,而且不会经过应用的服务器端。通过这个功能,我们能够实现多用户之间的互联,进行文件共享。

需要成功传输一个文件,我们需要如下几步:

通过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();
};

目前已经有两个文件共享的应用使用了这种方式:pubnub.github.io/rtc-pubnub-filesharegithub.com/Peer5/ShareFest,这两个应用都是开源的,并提供了基于RTCDataChannel的文件共享

那么我们能做什么?

RTCDataChannel为文件共享、多人游戏以及内容交付应用提供了全新的实现思路:

  • 上面已经提到了点对点的文件传输了
  • 多人游戏,与诸如WebGL等其他技术相结合,比如Mozilla的Banana Bread
  • 内容交付:由PeerCDN重新改造的一个用于提供点对点通信提供资源的框架

改变你构建应用的方式

现在我们可使用高新能、低延迟的RTCDataChannel来创建更优秀的应用了。一些框架,诸如PeerJSPubNub WebRTC SDK,使得RTCDataChannel更加易于使用,其API也被各个平台所支持

RTCDataChannel所带来的优势能够改变你在浏览器中传输数据的观念。

更多资讯

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容