WebRTC搭建前端視頻聊天室——數據通道篇

本文翻譯自WebRTC data channelsjavascript

在兩個瀏覽器中,爲聊天、遊戲、或是文件傳輸等需求發送信息是十分複雜的。一般狀況下,咱們須要創建一臺服務器來轉發數據,固然規模比較大的狀況下,會擴展成多個數據中心。這種狀況下很容易出現很高的延遲,同時難以保證數據的私密性。html

這些問題能夠經過WebRTC提供的RTCDataChannel API來解決,他能直接在點對點之間傳輸數據。這篇文章將介紹如何建立並使用數據通道,並提供了一些網絡上常見的用例html5

爲了充分理解這篇文章,你可能須要去了解一些RTCPeerConnection API的相關知識,以及STUN,TURN、信道如何工做。強烈推薦Getting Started With WebRTC這篇文章java


爲何咱們須要另一個數據通道

咱們已經有WebSocketAJAX服務器發送事件了,爲何咱們須要另一個通訊信道?WebSocket是全雙工的,但這些技術的設計都是讓瀏覽器與服務器之間進行通訊。git

RTCDataChannel則是一個徹底不一樣的途徑:github

  • 它經過RTCPeerConnection API,能夠創建點對點互聯。因爲不須要中介服務器,中間的「跳數」減小,延遲更低。
  • RTCDataChannel使用Stream Control Transmission Protocol(SCTP)協議,容許咱們配置傳遞語義:咱們能夠配置包傳輸的順序並提供重傳時的一些配置。

基於SCTP的支持的RTCDataChannel已經可以在桌面的Chrome、Opera和Firefox中使用,移動端則有Android支持。web


一個警告:信令、STUN和TURN

儘管WebRTC容許點對點的通訊,但它依然須要服務器:
* 信令傳輸:創建點對點的鏈接須要傳輸一些媒體和網絡相關的元數據信息,須要經過服務器
* NAT和防火牆穿透:咱們須要經過ICE框架來創建點與點之間的網絡路徑。可使用STUN服務器(肯定雙方的可公開訪問你的IP地址和端口)以及TURN服務器(若是直接鏈接失敗,就必須數據中繼了)chrome

WebRTC in the real world: STUN, TURN, and signaling 文章詳細介紹了WebRTC如何與這兩種服務器進行交互api


功能

RTCDataChannel API支持靈活的數據類型。它的API是模仿WebSocket設計的,而且支持JavaScript中的二進制類型如Blob、ArrayBuffer和ArrayBufferView,另外還支持字符串。這些類型對於文件傳輸和多玩家的遊戲來講意義重大。
這裏寫圖片描述
以上來自Ilya GrigorikHigh Performance Browser Networking瀏覽器

RTCDataChannel在不可靠模式(相似於UDP)或可靠模式(相似於TCP)下都可以正常工做。但這兩種模式有一些不一樣:

  • 可靠模式:保證消息傳輸必定成功,並保證按序到達。這天然須要必定量的開銷,速度也更慢
  • 不可靠模式:不保證消息傳輸必定成功,也不保證按序到達。這消除了那些開銷,速度也更快

在不會丟包的狀況下,這兩種模式的效率差很少。然而,可靠模式下,丟包將形成後續的全部包阻塞,丟失的數據包也將重傳直至其成功到達。固然,咱們能在同一個應用中使用多個數據通道,每個有他們本身的可靠性

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

配置數據通道

網上已經有不少RTCDataChannel的例子了:

ps:PubBub是一個實時信息通信應用開發公司

在這個例子中,瀏覽器建立了一個對等鏈接鏈接到本身。而後在這個對等鏈接n上建立了一個數據通道,發送了一些消息。最後,消息成功抵達並顯示在頁面上。

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
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來做區分,並提供一系列的配置選項:

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
var dataChannelOptions = { ordered: false, //不保證到達順序 maxRetransmitTime: 3000, //最大重傳時間 };

咱們能夠加入一個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標籤提供下載了:

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
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所帶來的優點可以改變你在瀏覽器中傳輸數據的觀念。


更多資訊

相關文章
相關標籤/搜索