WebRTC 及点对点网络通信机制
這是 JavaScript 工作原理第十八章。
概述
何為 WebRTC ?首先,字面上已經(jīng)給出了關(guān)于這一技術(shù)的大量信息,RTC 即為實時通信技術(shù)。
WebRTC 填補了網(wǎng)頁開發(fā)平臺中的一個重要空白。在以往,只有諸如桌面聊天程序這樣的 P2P 技術(shù)才能夠?qū)崿F(xiàn)實時通訊而網(wǎng)頁不行。但是 WebRTC 的出現(xiàn)改變了這一狀況。
WebRTC 本質(zhì)上允許網(wǎng)頁程序創(chuàng)建點對點通信,我們將會在隨后的章節(jié)中進行介紹。我們將討論如下主題,以便向開發(fā)者全面介紹 WebRTC 的內(nèi)部構(gòu)造:
- 點對點通信
- 防火墻和 NAT 穿透
- 信令,會話及協(xié)議
- WebRTC 接口
點對點通信
每個用戶的網(wǎng)頁瀏覽器必須按照如下步驟以實現(xiàn)通過網(wǎng)頁瀏覽器進行的點對點通信:
- 同意開始進行通信
- 知道如何定位另一個點
- 繞過安全和防火墻限制
- 實時傳輸所有多媒體通信信息
眾所周知,基于瀏覽器的點對點通信的最大挑戰(zhàn)之一即如何定位和建立與另一個網(wǎng)頁瀏覽器進行通信的網(wǎng)絡(luò)套接字以進行雙向數(shù)據(jù)傳輸。我們將會克服建立與此種網(wǎng)絡(luò)連接相關(guān)的困難。
每當(dāng)網(wǎng)頁程序需要數(shù)據(jù)或者靜態(tài)資源,會直接從相應(yīng)的服務(wù)器獲取,僅此而已。但是,如果若想要通過直接連接用戶的瀏覽器來建立點對點的視頻聊天就不可能,因為其它瀏覽器并不是一個已知的網(wǎng)頁服務(wù)器,所以用戶不知道需要建立視頻聊天的 IP 地址。所以,需要更多的技術(shù)以建立 p2p 連接。
防火墻和 NAT 穿透
一般電腦是不會被分配一個靜態(tài)公共 IP 地址的。原因是電腦是位于防火墻和網(wǎng)絡(luò)訪問轉(zhuǎn)換設(shè)備(NAT) 后面的。
一個 NAT 設(shè)備會把防火墻內(nèi)的私有 IP 地址轉(zhuǎn)換為一個公共 IP 地址。對于安全和有限的可用公共 IP 地址來說,NAT 設(shè)備是必須的。這也是為什么開發(fā)者的網(wǎng)頁程序不能夠把當(dāng)前設(shè)備看成擁有一個靜態(tài)公共 IP 地址的原因。
讓我們來了解下 NAT 設(shè)備的工作原理。當(dāng)開發(fā)者處于一個企業(yè)網(wǎng)中然后加入了 WIFI,那么電腦將會被分配一個只存在于 NAT 后面的 IP 地址。假設(shè)是 172.0.23.4。然而,對于外部而言,用戶的 IP 地址會是類似 164.53.27.98 這樣的。那么,外部會把所有請求看作來自 164.53.27.98 而 NAT 設(shè)備會保證來自于目標(biāo)用戶電腦的請求的響應(yīng)數(shù)據(jù)返回到相應(yīng)的內(nèi)部 172.0.23.4 IP 地址的電腦。這得歸功于映射表。注意到除了 IP 地址,網(wǎng)絡(luò)通信還需要通信端口。
隨著 NAT 設(shè)備參與其中,瀏覽器需要知道進行通信的目標(biāo)瀏覽器對應(yīng)的機器 IP 地址。
這個就需要用到 NAT 會話穿透程序(STUN)和 NAT 穿透中繼轉(zhuǎn)發(fā)服務(wù)器。為使用 WebRTC 技術(shù),開發(fā)者需要請求 STUN 服務(wù)器以獲得其公共 IP 地址。這就好像你的電腦請求遠(yuǎn)程服務(wù)器,詢問遠(yuǎn)程服務(wù)器發(fā)起查詢的客戶端 IP 地址。遠(yuǎn)程服務(wù)器會返回對應(yīng)的客戶端 IP 地址。
假設(shè)這一過程進展順利,那么開發(fā)者將會獲得一個公共 IP 地址和端口,這樣就可以告知其它點如何直接和你進行通信。同理,這些點也可以請求 STUN 或 TURN 服務(wù)器以獲得公共 IP 地址然后告知其通信地址。
信令,會話和協(xié)議
前述網(wǎng)絡(luò)信息檢索過程只是更大的信令話題的一部分,在 WebRTC 中,它是基于 JavaScript 會話構(gòu)建協(xié)議(JSEP)標(biāo)準(zhǔn)的。信令涉及網(wǎng)絡(luò)檢索和 NAT 穿透,會話創(chuàng)建及管理,通信安全,媒體功能元數(shù)據(jù)和調(diào)制及錯誤處理。
為了讓通信順利進行,節(jié)點必須確定元數(shù)據(jù)本地媒體環(huán)境(比如分辨率和編碼能力等)和收集可用的程序主機網(wǎng)絡(luò)地址。WebRTC 接口里面沒有集成反復(fù)傳輸這一重要信息的信令機制。
WebRTC 標(biāo)準(zhǔn)并沒有規(guī)定信令且沒有在接口中實現(xiàn)是為了能夠更加靈活地使用其它技術(shù)和協(xié)議。信令和處理信令的服務(wù)器是由 WebRTC 程序開發(fā)者控制的。
假設(shè)開發(fā)者基于瀏覽器的 WebRTC 程序使用之前所說的 STUN 服務(wù)器獲取其公共 IP 地址,那么,下一步即和其它點進行協(xié)商和建立網(wǎng)絡(luò)會話連接。
使用任意一個專門應(yīng)用于多媒體通信的信令/通信協(xié)議初始化會話協(xié)商和通信連接。該協(xié)議負(fù)責(zé)管理會話和中斷的規(guī)則。
會話初始協(xié)議(SIP) 是協(xié)議之一。多虧了 WebRTC 信令的靈活性,SIP 并不是唯一可供使用的信令協(xié)議。所選的通信協(xié)議必須和被稱為會話描述協(xié)議(SDP)的應(yīng)用層協(xié)議兼容,SDP 被應(yīng)用于 WebRTC。所有的多媒體指定元數(shù)據(jù)都是通過 SDP 協(xié)議進行數(shù)據(jù)傳輸?shù)摹?/p>
任意試圖和其它點進行通信的點(比如 WebRTC 程序)都會生成交互式連接建立協(xié)議(ICE)候選集。候選集表示一個可供使用的 IP 地址,端口及傳輸協(xié)議的集合。注意,一臺電腦可以擁有多個網(wǎng)絡(luò)接口(有線和無線等),因此可以擁有多個 IP 地址,每個接口分配一個 IP 地址。
以下為 MDN 上描繪這一通信交換的圖示:
建立連接
每個節(jié)點首先獲取之前所說的公共 IP 地址。之后動態(tài)創(chuàng)建「信道」信令數(shù)據(jù)來檢索其它節(jié)點并且支持點對點協(xié)商及創(chuàng)建會話。
這些「信道」不能夠被外部檢索和訪問到且只能通過唯一標(biāo)識符來訪問。
需要注意的是由于 WebRTC 的靈活性且事實上信令創(chuàng)建程序并沒有在標(biāo)準(zhǔn)中指定,使用的技術(shù)不同,「信道」的概念和使用會有些許異同。事實上,一些協(xié)議并不要求「通道」機制來進行通信。
本篇文章將會假設(shè)存在「信道」。
一旦兩個或者更多的點連接到相同的「信道」上,節(jié)點就可以進行通信和協(xié)商會話信息。這一過程和發(fā)布/訂閱模式有些許類似。大體上,初始點使用諸如會話初始協(xié)議(SIP)和 SDP 的信號協(xié)議發(fā)出一個「offer」的包。發(fā)起者等待連接到指定「通道」的接收者的「answer」應(yīng)答。
一旦接收到應(yīng)答,會開始選擇和協(xié)商由各個節(jié)點生成的最優(yōu)交互連接建立協(xié)調(diào)候選(ICE)集。一旦選定了最優(yōu) ICE 候選集,特別是確認(rèn)了所有節(jié)點通信所要求的元數(shù)據(jù),網(wǎng)絡(luò)路由(IP 地址和端口)及媒體信息。這樣就會完全建立及激活節(jié)點間的網(wǎng)絡(luò)套接字會話。緊接著,每個節(jié)點創(chuàng)建本地數(shù)據(jù)流和數(shù)據(jù)通道端點,然后,最后使用任意雙向通信技術(shù)來傳輸多媒體數(shù)據(jù)。
如果確認(rèn)最優(yōu) ICE 候選的過程失敗了,這樣的情況經(jīng)常發(fā)生于使用的防火墻和 NAT 技術(shù),后備使用 TURN 服務(wù)器作為中繼轉(zhuǎn)發(fā)服務(wù)器。這一過程主要是使用一臺服務(wù)器作為中間媒介,然后在節(jié)點間轉(zhuǎn)發(fā)傳輸數(shù)據(jù)。請注意這不是真正的點對點通信,因為真正的點對點通信是節(jié)點之間直接進行雙向數(shù)據(jù)傳輸。
每當(dāng)使用 TURN 作為后備通信的時候,每個節(jié)點將不必知道如何連接并傳輸數(shù)據(jù)給對方節(jié)點。相反,節(jié)點只需要知道在會話通信期間實時發(fā)送和接收多媒體數(shù)據(jù)的公共 TURN 服務(wù)器。
需要重點理解的是這僅僅只是一個失敗保護和最后手段。TURN 服務(wù)器需要相當(dāng)健壯,擁有昂貴帶寬和強大的處理能力及處理潛在的大量數(shù)據(jù)。因此,使用 TURN 服務(wù)器會明顯增加額外的開銷和復(fù)雜度。
WebRTC 接口
WebRTC 中包含三種主要接口:
- 媒體捕捉和流-允許開發(fā)者訪問諸如麥克風(fēng)和網(wǎng)絡(luò)攝像機的輸入設(shè)備。該接口允許開發(fā)者獲取麥克風(fēng)或者網(wǎng)絡(luò)攝像機媒體流。
- RTCPeerConnection-開發(fā)者實時傳輸獲取的視頻和音頻流到另一個 WebRTC 端點。開發(fā)者使用這些接口連接本地機器和遠(yuǎn)程節(jié)點。該接口提供創(chuàng)建到遠(yuǎn)程節(jié)點的連接,維護和監(jiān)視連接及關(guān)閉不再活躍的連接的方法。
- RTCDataChannel-該接口允許開發(fā)者傳輸任意數(shù)據(jù)。每個數(shù)據(jù)通道都和 RTCPeerConnection 有關(guān)。
我們將分別介紹這三類接口。
媒體捕捉和流
媒體捕捉和流接口經(jīng)常被稱為媒體流接口或者流接口,該接口支持音頻或者視頻數(shù)據(jù)流數(shù)據(jù),處理音視頻流的方法,與數(shù)據(jù)類型相關(guān)的約束,異步獲取數(shù)據(jù)時的成功和錯誤回調(diào)及 API 調(diào)用過程中觸發(fā)的事件。
MediaDevices 的 getUserMedia() 方法提示用戶授權(quán)允許使用媒體輸入設(shè)備,創(chuàng)建一個包含指定媒體類型軌道的媒體流。該媒體流,可包括諸如視頻軌道(由諸如攝像機,視頻錄制設(shè)備,屏幕共享服務(wù)等硬件或者虛擬視頻源所創(chuàng)建),音頻軌道(與視頻類似,由諸如麥克風(fēng),A/D 轉(zhuǎn)換器等的物理或者虛擬音頻源所創(chuàng)建)且有可能是其它類型軌道。
該方法返回一個 Promise 并解析為 MediaStream 對象。當(dāng)用戶拒絕授權(quán)或者沒有可用的匹配媒體資源,promise 會分別返回 PermissionDeniedError 或者 NotFoundError。
可以通過 navigator 對象訪問 MediaDevice 單例:
navigator.mediaDevices.getUserMedia(constraints) .then(function(stream) {/* 使用流 */ }) .catch(function(err) {/* 處理錯誤 */ });注意這里需要傳入 constraints 對象以指定返回的媒體流類型。開發(fā)者可以進行各種配置,包括使用的攝像頭(前置或后置),幀頻率,分辨率等等。
從版本 25 起,基于 Chromium 的瀏覽器已經(jīng)允許通過 getUserMedia() 獲取的音頻數(shù)據(jù)賦值給音頻或者視頻元素(但需要注意的是媒體元素默認(rèn)值為空)。
可以把 getUserMedia作為網(wǎng)頁音頻接口的輸入節(jié)點:
function gotStream(stream) {window.AudioContext = window.AudioContext || window.webkitAudioContext;var audioContext = new AudioContext();// 從流創(chuàng)建音頻節(jié)點var mediaStreamSource = audioContext.createMediaStreamSource(stream);// 把它和目標(biāo)節(jié)點進行連接讓自己傾聽或由其它節(jié)點處理mediaStreamSource.connect(audioContext.destination); }navigator.getUserMedia({audio:true}, gotStream);隱私限制
由于該接口可能導(dǎo)致明顯的隱私問題,規(guī)范在通知用戶和權(quán)限管理方面對 getUserMedia() 方法有非常明確的規(guī)定。在打開諸如用戶網(wǎng)頁攝像頭或者麥克風(fēng)的媒體輸入設(shè)備的時候getUserMedia() 必須總是獲取用戶的授權(quán)。
瀏覽器可能提供每個域名授權(quán)一次的權(quán)限功能,但必須至少第一次詢問授權(quán),然后用戶必須指定授權(quán)的權(quán)限。
通知中的規(guī)則同樣重要。除了可能存在其它硬件指示器,瀏覽器還必須顯示一個窗口顯示使用中的攝像頭或者麥克風(fēng)。即使當(dāng)時設(shè)備沒有進行錄制,瀏覽器必須顯示一個提示窗口提示已授權(quán)使用哪個設(shè)備作為輸入設(shè)備。
RTCPeerConnection
RTCPeerConnection 表示一個本地電腦和遠(yuǎn)程節(jié)點之間的 WebRTC 連接。它提供了連接遠(yuǎn)程節(jié)點,維護和監(jiān)視連接及關(guān)閉不再活躍的連接的方法。
如下為一張 WebRTC 圖表展示 了 RTCPeerConnection 的角色:
從 JavaScript 方面看 ,圖中需要理解的主要方面即 RTCPeerConnection 把復(fù)雜的底層內(nèi)部結(jié)構(gòu)的復(fù)雜度抽象為一個接口給開發(fā)者。WebRTC 所使用的編碼和協(xié)議為即使在不穩(wěn)定的網(wǎng)絡(luò)環(huán)境下仍然能夠創(chuàng)建一個盡可能實時的通信而做了大量的工作:
- 包丟失恢復(fù)
- 回音消除
- 網(wǎng)絡(luò)自適應(yīng)
- 視頻抖動緩沖
- 自動增益控制
- 噪聲減少和壓制
- 圖像「清潔」
RTCDataChannel
不僅僅是音視頻,WebRTC 還支持實時傳輸其它類型的數(shù)據(jù)。
RTCDataChannel 接口允許點對點交換任意數(shù)據(jù)。
該接口有許多用途,包括:
- 游戲
- 實時文本聊天
- 文件傳輸
- 分布式網(wǎng)絡(luò)
該接口有幾項功能,充分利用 RTCPeerConnection 并創(chuàng)建強大和靈活的點對點通信:
- 使用RTCPeerConnection 創(chuàng)建會話
- 包含優(yōu)先級的多個并發(fā)通道
- 可靠和不可靠消息傳遞語義
- 內(nèi)置安全(DTLS)和消息堵塞控制
語法和已有的 WebSocket 類似,包含有 send() 方法和 message 事件:
var peerConnection = new webkitRTCPeerConnection(servers,{optional: [{RtpDataChannels: true}]} );peerConnection.ondatachannel = function(event) {receiveChannel = event.channel;receiveChannel.onmessage = function(event){document.querySelector("#receiver").innerHTML = event.data;}; };sendChannel = peerConnection.createDataChannel("sendDataChannel", {reliable: false});document.querySelector("button#send").onclick = function (){var data = document.querySelector("textarea#send").value;sendChannel.send(data); };由于通信是直接在瀏覽器之間進行的,所以 RTCDataChannel 會比 WebSocket 更快即使是使用中繼轉(zhuǎn)發(fā)服務(wù)器(TURN)。
WebRTC 實際應(yīng)用
在實際應(yīng)用中,WebRTC 需要服務(wù)器,但這很簡單,因此會發(fā)生如下步驟:
- 用戶各自檢索節(jié)點然后交換諸如名字的詳情。
- WebRTC 客戶端程序(點)交換網(wǎng)絡(luò)信息。
- 點交換諸如視頻格式和分辨率的媒體信息。
- WebRTC 客戶端程序穿透 NAT 網(wǎng)關(guān) 和防火墻。
換句話說,WebRTC 需要四種類型的服務(wù)端功能:
- 用戶檢索和通信
- 發(fā)信號
- NAT/防火墻穿透
- 中繼轉(zhuǎn)發(fā)服務(wù)器以防點對點通信失敗
ICE 使用 STUN 協(xié)議及其擴展 TURN 協(xié)議來創(chuàng)建 RTCPeerConnection 連接來處理 NAT 穿透和其它網(wǎng)絡(luò)變化。
如前所述,ICE 是用來連接諸如兩個視頻聊天客戶的節(jié)點協(xié)議。一開始,ICE 會試圖使用最低的可能的網(wǎng)絡(luò)延遲即使用 UDP 來直接連接節(jié)點。在這一過程中,STUN 服務(wù)器只有一個任務(wù):讓位于 NAT 之后的節(jié)點能夠找到其公共地址和端口。開發(fā)者可以查看一下可用的 STUN 服務(wù)器(Google 也有一堆) 名單。
檢索連接候選
若 UDP 失敗,ICE 嘗試 TCP,先 HTTP 后 HTTPS。如果直接連接失敗-特殊情況下,由于企業(yè) NAT 穿透和防火墻-ICE 使用中間(轉(zhuǎn)發(fā)) TURN 服務(wù)器。換句話說,ICE 首先通過 UDP 使用 STUN 服務(wù)器來直接連接節(jié)點,若失敗則后備使用 TURN 中繼轉(zhuǎn)發(fā)服務(wù)器。「檢索連接候選者」指的是檢索網(wǎng)絡(luò)接口和端口的過程。
安全性
實時通信程序或者插件可能造成幾種安全問題。例如:
- 未加密媒體或者數(shù)據(jù)有可能會在瀏覽器之間或者瀏覽器和服務(wù)器之間被竊取。
- 程序有可能在未經(jīng)用戶授權(quán)同意的情況下記錄和分發(fā)音視頻。
- 可疑軟件或者病毒有可能會隨著表面上無害的插件或者程序一起安裝。
WebRTC 有幾種方法用來解決如上問題:
- WebRTC 實現(xiàn)使用諸如 DTLS 和 SRTP 的安全協(xié)議。
- 包括信令機制在內(nèi)的所有 WebRTC 組件都是強制加密的。
- WebRTC 不是一個插件:其組件運行于瀏覽器沙箱之中且不是在一個單獨的進程之中,不需要單獨安裝組件且隨著瀏覽器升級而更新。
- 攝像頭和麥克風(fēng)必須顯式授權(quán)且當(dāng)攝像頭或者麥克風(fēng)運行時,必須在用戶窗口中有所顯示。
對于需要實現(xiàn)一些瀏覽器之間實時通信流功能的產(chǎn)品而言,WebRTC 是一個令人難以置信和強大的技術(shù)。
參考資料:
- https://www.html5rocks.com/en...
- https://www.innoarchitech.com...
總結(jié)
以上是生活随笔為你收集整理的WebRTC 及点对点网络通信机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小程序上传图片到七牛云(支持多张上传,预
- 下一篇: 如何用“区块链+稳定币”技术来提升资产证