使用WebRTC搭建前端視頻聊天室——數(shù)據(jù)通道篇

本文翻譯自WebRTC data channels

在兩個(gè)瀏覽器中,為聊天隔心、游戲、或是文件傳輸?shù)刃枨蟀l(fā)送信息是十分復(fù)雜的尚胞。通常情況下硬霍,我們需要建立一臺(tái)服務(wù)器來(lái)轉(zhuǎn)發(fā)數(shù)據(jù),當(dāng)然規(guī)模比較大的情況下笼裳,會(huì)擴(kuò)展成多個(gè)數(shù)據(jù)中心唯卖。這種情況下很容易出現(xiàn)很高的延遲粱玲,同時(shí)難以保證數(shù)據(jù)的私密性。

這些問(wèn)題可以通過(guò)WebRTC提供的RTCDataChannel API來(lái)解決拜轨,他能直接在點(diǎn)對(duì)點(diǎn)之間傳輸數(shù)據(jù)抽减。這篇文章將介紹如何創(chuàng)建并使用數(shù)據(jù)通道,并提供了一些網(wǎng)絡(luò)上常見(jiàn)的用例

為了充分理解這篇文章橄碾,你可能需要去了解一些RTCPeerConnection API的相關(guān)知識(shí)卵沉,以及STUN,TURN法牲、信道如何工作偎箫。強(qiáng)烈推薦Getting Started With WebRTC這篇文章

為什么我們需要另外一個(gè)數(shù)據(jù)通道

我們已經(jīng)有WebSocketAJAX服務(wù)器發(fā)送事件了皆串,為什么我們需要另外一個(gè)通信信道淹办?WebSocket是全雙工的,但這些技術(shù)的設(shè)計(jì)都是讓瀏覽器與服務(wù)器之間進(jìn)行通信恶复。

RTCDataChannel則是一個(gè)完全不同的途徑:

  • 它通過(guò)RTCPeerConnection API怜森,可以建立點(diǎn)對(duì)點(diǎn)互聯(lián)。由于不需要中介服務(wù)器谤牡,中間的“跳數(shù)”減少副硅,延遲更低。
  • RTCDataChannel使用Stream Control Transmission Protocol(SCTP)協(xié)議翅萤,允許我們配置傳遞語(yǔ)義:我們可以配置包傳輸?shù)捻樞虿⑻峁┲貍鲿r(shí)的一些配置恐疲。

基于SCTP的支持的RTCDataChannel已經(jīng)能夠在桌面的Chrome、Opera和Firefox中使用套么,移動(dòng)端則有Android支持培己。

一個(gè)警告:信令、STUN和TURN

盡管WebRTC允許點(diǎn)對(duì)點(diǎn)的通信胚泌,但它依然需要服務(wù)器:

  • 信令傳輸:建立點(diǎn)對(duì)點(diǎn)的連接需要傳輸一些媒體和網(wǎng)絡(luò)相關(guān)的元數(shù)據(jù)信息省咨,需要通過(guò)服務(wù)器
  • NAT和防火墻穿透:我們需要通過(guò)ICE框架來(lái)建立點(diǎn)與點(diǎn)之間的網(wǎng)絡(luò)路徑$枋遥可以使用STUN服務(wù)器(確定雙方的可公開(kāi)訪問(wèn)你的IP地址和端口)以及TURN服務(wù)器(如果直接連接失敗零蓉,就必須數(shù)據(jù)中繼了)

WebRTC in the real world: STUN, TURN, and signaling

文章詳細(xì)介紹了WebRTC如何與這兩種服務(wù)器進(jìn)行交互

功能

RTCDataChannel API支持靈活的數(shù)據(jù)類(lèi)型。它的API是模仿WebSocket設(shè)計(jì)的穷缤,并且支持JavaScript中的二進(jìn)制類(lèi)型如Blob敌蜂、ArrayBuffer和ArrayBufferView,另外還支持字符串津肛。這些類(lèi)型對(duì)于文件傳輸和多玩家的游戲來(lái)說(shuō)意義重大章喉。

[圖片上傳失敗...(image-813875-1513063558572)]

以上來(lái)自Ilya GrigorikHigh Performance Browser Networking

RTCDataChannel在不可靠模式(類(lèi)似于UDP)或可靠模式(類(lèi)似于TCP)下都能夠正常工作。但這兩種模式有一些不同:

  • 可靠模式:保證消息傳輸一定成功,并保證按序到達(dá)囊陡。這自然需要一定量的開(kāi)銷(xiāo)芳绩,速度也更慢
  • 不可靠模式:不保證消息傳輸一定成功,也不保證按序到達(dá)撞反。這消除了那些開(kāi)銷(xiāo)妥色,速度也更快

在不會(huì)丟包的情況下,這兩種模式的效率差不多遏片。然而嘹害,可靠模式下,丟包將造成后續(xù)的所有包阻塞吮便,丟失的數(shù)據(jù)包也將重傳直至其成功到達(dá)笔呀。當(dāng)然,我們能在同一個(gè)應(yīng)用中使用多個(gè)數(shù)據(jù)通道髓需,每一個(gè)有他們自己的可靠性

下面將說(shuō)明如何去配置可靠模式或不可靠模式的RTCDataChannel

配置數(shù)據(jù)通道

網(wǎng)上已經(jīng)有很多RTCDataChannel的例子了:

simpl.info/dc

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

pubnub.github.io/webrtc(兩個(gè)PubNub用戶)

ps:PubBub是一個(gè)實(shí)時(shí)信息通訊應(yīng)用開(kāi)發(fā)公司

在這個(gè)例子中许师,瀏覽器創(chuàng)建了一個(gè)對(duì)等連接連接到自己。然后在這個(gè)對(duì)等連接n上創(chuàng)建了一個(gè)數(shù)據(jù)通道僚匆,發(fā)送了一些消息微渠。最后,消息成功抵達(dá)并顯示在頁(yè)面上咧擂。

var peerConnection = new RTCPeerConnection();

//使用信令傳輸信道創(chuàng)建對(duì)等連接
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對(duì)象建立在一個(gè)已經(jīng)創(chuàng)建完畢的對(duì)等連接之上逞盆。它可以創(chuàng)建在信令傳輸前后。另外松申,可以賦予一個(gè)label來(lái)作區(qū)分云芦,并提供一系列的配置選項(xiàng):

var dataChannelOptions = {
  ordered: false, //不保證到達(dá)順序
  maxRetransmitTime: 3000, //最大重傳時(shí)間
};

我們可以加入一個(gè)maxRetransimits選項(xiàng)(最大重傳次數(shù)),但maxRetransimitTimemaxRetransimits只能設(shè)定一個(gè)贸桶,不能兩個(gè)懂事設(shè)定舅逸。如果想使用UDP的方式,設(shè)定maxRetransmits為0刨啸,orderedfalse堡赔。如果想要獲取更多信息,請(qǐng)查看RFC 4960(SCTP)和RFC 3758(SCTP部分可靠性)

  • ordered: 數(shù)據(jù)通道是否保證按序傳輸數(shù)據(jù)
  • maxRetrasmitTime:在信息失敗前的最大重傳時(shí)間(強(qiáng)迫進(jìn)入不可靠模式)
  • maxRetransmits:在信息失敗前的最大重傳次數(shù)(強(qiáng)迫進(jìn)入不可靠模式)
  • protocol:允許使用一個(gè)自協(xié)議设联,但如果協(xié)議不支持,將會(huì)失敗
  • negotiated:如果設(shè)為true灼捂,將一處對(duì)方的數(shù)據(jù)通道的自動(dòng)設(shè)置离例,也就是說(shuō),將使用相同的id以自己配置的方式與對(duì)方建立數(shù)據(jù)通道
  • id:為數(shù)據(jù)通道提供一個(gè)自己定義的ID

它安全嗎悉稠?

在WebRTC所有的組件中宫蛆,都會(huì)強(qiáng)制進(jìn)行加密。在RTCDataChannel中,所有的數(shù)據(jù)都使用數(shù)據(jù)報(bào)傳輸層安全性(DTLS)耀盗。DTLS是SSL的衍生想虎,也就是說(shuō),你的數(shù)據(jù)將和使用基于SSL的連接一樣安全叛拷。DTLS已經(jīng)被標(biāo)準(zhǔn)化舌厨,并內(nèi)置于所有支持WebRTC的瀏覽器中。如果需要更多關(guān)于DTLS信息忿薇,請(qǐng)?jiān)L問(wèn)Wireshark的維基

改變你考慮數(shù)據(jù)的方式

處理大批量的數(shù)據(jù)裙椭,一直是JavaScript的一個(gè)難點(diǎn)。正如Sharefest所提出的觀點(diǎn)署浩,我們需要用一種新的方式來(lái)考慮數(shù)據(jù)揉燃。如果你需要傳輸一個(gè)比你當(dāng)前可用內(nèi)存更大的文件,就必須考慮新的保存信息的方式了筋栋。這也就是像FileSystem API等技術(shù)存在的意義炊汤。我們將在下面進(jìn)行介紹

搭建一個(gè)文件共享應(yīng)用

現(xiàn)在我們可以通過(guò)RTCDataChannel來(lái)創(chuàng)建文件共享應(yīng)用。將應(yīng)用建立在RTCDataChannel智商也意味著傳輸?shù)奈募?shù)據(jù)都將加密弊攘,而且不會(huì)經(jīng)過(guò)應(yīng)用的服務(wù)器端婿崭。通過(guò)這個(gè)功能,我們能夠?qū)崿F(xiàn)多用戶之間的互聯(lián)肴颊,進(jìn)行文件共享氓栈。

需要成功傳輸一個(gè)文件承匣,我們需要如下幾步:

通過(guò)JavaScript的File API讀取文件數(shù)據(jù)
2. 使用RTCPeerConnection在用戶間創(chuàng)建一個(gè)對(duì)等連接
3. 使用RTCDataChannel在用戶間創(chuàng)建一個(gè)數(shù)據(jù)通道

在使用RTCDataChannel時(shí)创夜,還有一些其他問(wèn)題需要考慮:

文件大小:如果文件很小,能夠直接通過(guò)一個(gè)Blob進(jìn)行存儲(chǔ)和讀取叉瘩,那么我們可以直接使用File API將其讀進(jìn)內(nèi)存竟宋,并通過(guò)可靠的數(shù)據(jù)通道發(fā)送(但是需要注意的是提完,瀏覽器有最大傳輸大小的限制)。隨著文件變大的話丘侠,就不那么簡(jiǎn)單了徒欣。我們需要一個(gè)分塊機(jī)制:文件將分成多個(gè)碎片,稱(chēng)為文件塊蜗字。我們不再直接發(fā)送整個(gè)文件打肝,而是一次發(fā)送一個(gè)文件塊。當(dāng)然文件塊上會(huì)有一些元數(shù)據(jù)如塊的ID挪捕,方便對(duì)方能夠識(shí)別粗梭。接收到文件塊之后,首先將這些文件塊保存在離線存儲(chǔ)中(例如级零,使用FileSystem API)断医,只有當(dāng)所有塊都接收完畢,才將其拼合起來(lái)成為完整的文件,保存到用戶的硬盤(pán)鉴嗤。

速度:文件傳輸更適合使用可靠模式(像TCP)還是非可靠模式(像UDP)還有待商榷斩启。如果應(yīng)用知識(shí)簡(jiǎn)單的一對(duì)一文件傳輸,使用不可靠的數(shù)據(jù)通道將需要設(shè)計(jì)一定的響應(yīng)/重傳協(xié)議醉锅。你必須自己來(lái)實(shí)現(xiàn)它兔簇,就算你非常優(yōu)秀,它仍然不會(huì)比使用可靠的數(shù)據(jù)傳輸快多少荣挨∧腥停可靠而無(wú)序的數(shù)據(jù)通道將會(huì)更加合適,但是如果是多方文件傳輸默垄,結(jié)果可能會(huì)有所不同此虑。

塊大小:這些是你的應(yīng)用中的最小的“原子”數(shù)據(jù)。目前有傳輸大小限制(盡管以后可能不會(huì)有限制)口锭,所以必須要進(jìn)行分塊朦前。目前建議的最大塊大小為16KB。

如果文件已經(jīng)被完全傳輸鹃操,就可以使用一個(gè)a標(biāo)簽提供下載了:

function saveFile(blob) {
  var link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'File Name';
  link.click();
};

目前已經(jīng)有兩個(gè)文件共享的應(yīng)用使用了這種方式:pubnub.github.io/rtc-pubnub-filesharegithub.com/Peer5/ShareFest韭寸,這兩個(gè)應(yīng)用都是開(kāi)源的,并提供了基于RTCDataChannel的文件共享

那么我們能做什么荆隘?

RTCDataChannel為文件共享恩伺、多人游戲以及內(nèi)容交付應(yīng)用提供了全新的實(shí)現(xiàn)思路:

  • 上面已經(jīng)提到了點(diǎn)對(duì)點(diǎn)的文件傳輸了
  • 多人游戲,與諸如WebGL等其他技術(shù)相結(jié)合椰拒,比如Mozilla的Banana Bread
  • 內(nèi)容交付:由PeerCDN重新改造的一個(gè)用于提供點(diǎn)對(duì)點(diǎn)通信提供資源的框架

改變你構(gòu)建應(yīng)用的方式

現(xiàn)在我們可使用高新能晶渠、低延遲的RTCDataChannel來(lái)創(chuàng)建更優(yōu)秀的應(yīng)用了。一些框架燃观,諸如PeerJSPubNub WebRTC SDK褒脯,使得RTCDataChannel更加易于使用,其API也被各個(gè)平臺(tái)所支持

RTCDataChannel所帶來(lái)的優(yōu)勢(shì)能夠改變你在瀏覽器中傳輸數(shù)據(jù)的觀念缆毁。

更多資訊

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末番川,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脊框,更是在濱河造成了極大的恐慌颁督,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缚陷,死亡現(xiàn)場(chǎng)離奇詭異适篙,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)箫爷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人虎锚,你說(shuō)我怎么就攤上這事硫痰。” “怎么了窜护?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵效斑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我柱徙,道長(zhǎng)缓屠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任护侮,我火速辦了婚禮敌完,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘羊初。我一直安慰自己滨溉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布长赞。 她就那樣靜靜地躺著晦攒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪得哆。 梳的紋絲不亂的頭發(fā)上脯颜,一...
    開(kāi)封第一講書(shū)人閱讀 52,874評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音贩据,去河邊找鬼栋操。 笑死,一個(gè)胖子當(dāng)著我的面吹牛乐设,可吹牛的內(nèi)容都是我干的讼庇。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼近尚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蠕啄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起戈锻,我...
    開(kāi)封第一講書(shū)人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤歼跟,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后格遭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體哈街,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年拒迅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骚秦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片她倘。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖作箍,靈堂內(nèi)的尸體忽然破棺而出硬梁,到底是詐尸還是另有隱情,我是刑警寧澤胞得,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布荧止,位于F島的核電站,受9級(jí)特大地震影響阶剑,放射性物質(zhì)發(fā)生泄漏跃巡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一牧愁、第九天 我趴在偏房一處隱蔽的房頂上張望素邪。 院中可真熱鬧,春花似錦递宅、人聲如沸娘香。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)烘绽。三九已至,卻和暖如春俐填,著一層夾襖步出監(jiān)牢的瞬間安接,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工英融, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盏檐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓驶悟,卻偏偏與公主長(zhǎng)得像胡野,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痕鳍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容