摘要:如果對和不太了解的同學,可以先閱讀如下文章的使用搭建前端視頻聊天室信令篇使用搭建前端視頻聊天室入門篇老劉和老姚當然服務器完全不參與其中,顯然是不可能的,用戶需要通過服務器上存儲的信息,才能確定需要和誰建立連接。
WebRTC給我們帶來了瀏覽器中的視頻、音頻聊天體驗。但個人認為,它最實用的特性莫過于DataChannel——在瀏覽器之間建立一個點對點的數據通道。在DataChannel之前,瀏覽器到瀏覽器的數據傳遞通常是這樣一個流程:瀏覽器1發送數據給服務器,服務器處理,服務器再轉發給瀏覽器2。這三個過程都會帶來相應的消耗,占用服務器帶寬不說,還減緩了消息從發送到接收的時間。其實最理想的方式就是瀏覽器1直接與瀏覽2進行通信,服務器不需要參與其中。WebRTC DataChannel就提供了這樣一種方式。
如果對WebRTC和DataChannel不太了解的同學,可以先閱讀如下文章:
- WebRTC的RTCDataChannel
- 使用WebRTC搭建前端視頻聊天室——信令篇
- 使用WebRTC搭建前端視頻聊天室——入門篇
當然服務器完全不參與其中,顯然是不可能的,用戶需要通過服務器上存儲的信息,才能確定需要和誰建立連接。這里通過一個故事來講述建立連接的過程:
不如釣魚去一些背景:
- 老劉和老姚都住在同一個小區但不同的片區,小區很破舊,沒有電話
- 片區相互隔離且片區門口有個保安,保安只認識自己片區的人,遇到不認識的人就需要查詢憑證才能通過,而憑證需要找物業才能確定
- 門衛老大爺認識小區里的所有人但是不知道都住哪,有什么消息都可以在出入小區的時候代為傳達
現在,老劉聽說老姚釣魚技術高超,想和老姚討論釣魚技巧。只要老劉和老姚相互之間知道對方的門牌號以及憑證,就可以串門了:
門衛老大爺認識老劉和老姚
老劉找物業確定了自己片區的出入憑證,將憑證、自己的門牌號以及意圖告訴門衛老大爺,讓其轉交給老姚
老姚買菜歸來遇到門衛老大爺,門衛老大爺將老劉的消息傳達給老姚。于是老姚知道怎么去老劉家了
老姚很開心,他也找物業獲取了自己小區的憑證,并將憑證、自己的門牌號等信息交給門衛老大爺,希望他傳達給老劉
老劉吃早餐回來遇到門衛老大爺,老大爺把老姚的小區憑證、門牌號等信息告訴老劉,這樣老劉就知道了怎么去老姚家了
老劉和老姚相互之間知道了對方的門牌號和小區出入憑證,他們相互之間有什么需要交流的直接串門就行了,消息不再需要門衛老大爺來代為傳達了
換個角度我們把角色做一個映射:
- 老劉:瀏覽器1
- 老姚:瀏覽器2
- 片區:不同網段
- 保安:防火墻
- 片區憑證:ICE candidate
- 物業:ICE server
- 門牌號:session description
- 門衛老大爺:server
于是乎故事就變成了這樣:
瀏覽器1和瀏覽器2在server上注冊,并保有連接
瀏覽器1從ice server獲取ice candidate并發送給server,并生成包含session description的offer,發送給server
server發送瀏覽器1的offer和ice candidate給瀏覽器2
瀏覽器2發送包含session description的answer和ice candidate給server
server發送瀏覽器2的answer和ice candidate給瀏覽器1
這樣,就建立了一個點對點的信道,流程如下所示:
禮物 故事老劉和老姚已經可以相互串門了,經過一段時間的交流感情越來越深。老姚的親友送了20斤葡萄給老姚,老姚決定送10斤給老劉。老姚畢竟年事已高,不可能一次帶10斤。于是乎,老姚將葡萄分成了10份,每次去老劉家串門就送一份過去。
這里可以做如下類比:
1. 10斤葡萄:一個文件(盡管文件分片沒有意義,葡萄分開還可以多帶帶吃,但是實在找不到啥好的比喻了)
2. 分成10份:將文件分片,轉成多個chunk
3. 老姚一次只能帶一斤:datachannel每次傳輸的數據量不宜太大(找到最合適的大小)
這其實就是通過datachannel傳輸文件的方式,首先將文件分片,然后逐個發送,最后再統一的進行組合成一個新的文件
分片通過HTML5的File API可以將type為file的input選中的文件讀取出來,并轉換成data url字符串。這也就為我們提供了很方便的分片方式:
var reader = new window.FileReader(file); reader.readAsDataURL(file); reader.onload = function(event, text) { chunkify(event.target.result);//將數據分片 };組合
通過datachannel發送的分片數據,我們需要將其進行組合,由于是data url字符串,在接收到所有包之后進行拼接就可以了。拼接完成后就得到了一個文件完整的data url字符串,那么我們如何將這個字符串轉換成文件呢?
方案一:直接跳轉下載既然是個dataurl,我們直接將其賦值給window.location.href自然可以下載,但是這樣下載是沒法設定下載后的文件名的,這想一想都蛋疼
方案二:通過a標簽下載這個原理和跳轉下載類似,都是使用dataurl本身的特性,通過創建一個a標簽,將dataurl字符串賦值給href屬性,然后使用download確定下載后的文件名,就可以完成下載了。但是很快又有新問題了,稍微大一點的文件下載的時候頁面崩潰了。這是因為dataurl有大小限制
方案三:blob其實可以通過給a標簽創建blob url的方式來進行下載,這個沒有大小限制。但是我們手上是dataurl,所以需要先進行轉換:
function dataURItoBlob(dataURI, dataTYPE) { var binary = atob(dataURI.split(",")[1]), array = []; for (var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i)); return new Blob([new Uint8Array(array)], { type: dataTYPE }); }
獲得blob后,我們就可以通過URL API來下載了:
var a = document.createElement("a"); document.body.appendChild(a); a.style = "display: none"; var blob = dataURItoBlob(data, "octet/stream"); var url = window.URL.createObjectURL(blob); a.href = url; a.download = filename; a.click(); !moz && window.URL.revokeObjectURL(url); a.parentNode.removeChild(a);
這里有幾個點:
1. datachannel其實是可以直接傳送blob的,但是只有ff支持,所以傳data url
2. chrome下載是直接觸發的,不會進行詢問,firefox會先詢問后下載,在詢問過程中如果執行了revokeObjectURL,下載就會取消,囧
如我們所知,WebRTC最有特點的地方其實是可以傳輸getUserMedia獲得的視頻、音頻流,來實現視頻聊天。但事實上我們的使用習慣來看,一般人不會一開始就打開視頻聊天,而且視頻聊天時很消耗內存的(32位機上一個連接至少20M左右好像,也有可能有出入)。所以常見的需求是,先建立一個包含datachannel的連接用于傳輸數據,然后在需要時升級成可以傳輸視頻、音頻。
看看我們之前傳輸的session description,它其實來自Session Description Protocol。可以看到wiki上的介紹:
The Session Description Protocol (SDP) is a format for describing streaming media initialization parameters.
這意味著什么呢?我們之前建立datachannel是沒有加視頻、音頻流的,而這個流的描述是寫在SDP里面的。現在我們需要傳輸視頻、音頻,就需要添加這些描述。所以就得重新獲得SDP,然后構建offer和answer再傳輸一次。傳輸的流程和之前一樣,沒什么區別。但這一次,我們不需要傳輸任何的ice candidate,這里我曾經遇到了坑,經過國外大大的點撥才明白過來。
Peertcfrom mattm: You do not need to send ICE candidates on an already established peer connection. The ICE candidates are to make sure the two peers can establish a connection through their potential NAT and firewalls. If you can already send data on the peer connection, ICE candidates will not do anything.
我將datachannel和websocket組合,實現了一個構建點對點連接的庫Peertc,它提供非常簡潔的方式來建立連接和發送數據、文件和視頻/音頻流,詳情見github。走過路過的記得star一下哦,有什么bug也非常希望能夠提出來。
最后WebRTC的點對點方式能夠運用在很多場景:
- 如web qq這種Web IM工具,這就不說了
- 如象棋這種雙人對戰游戲,每一步的數據服務器時不關心的,所以完全可以點對點發送
- 一對一在線面試、在線教育,這其實是即時通信的一個業務方向
- 視頻裸(),當我沒說
就醬,另外打個廣告及拉點搜索引擎權重:我的博客
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64169.html
摘要:在處于使用了設備的私有網絡中的主機之間需要建立連接時需要使用穿越技術。目前已經有很多穿越技術,但沒有一項是完美的,因為的行為是非標準化的。 什么是WebRTC? 眾所周知,瀏覽器本身不支持相互之間直接建立信道進行通信,都是通過服務器進行中轉。比如現在有兩個客戶端,甲和乙,他們倆想要通信,首先需要甲和服務器、乙和服務器之間建立信道。甲給乙發送消息時,甲先將消息發送到服務器上,服務器對甲...
摘要:最后,消息成功抵達并顯示在頁面上。在中,所有的數據都使用數據報傳輸層安全性。如果應用知識簡單的一對一文件傳輸,使用不可靠的數據通道將需要設計一定的響應重傳協議。目前建議的最大塊大小為。 本文翻譯自WebRTC data channels 在兩個瀏覽器中,為聊天、游戲、或是文件傳輸等需求發送信息是十分復雜的。通常情況下,我們需要建立一臺服務器來轉發數據,當然規模比較大的情況下,會擴展成...
摘要:使用能使得狀態被保存在服務器上會話描述協議將客戶端之間傳遞的信令分為兩種信令和信令。他們主要內容的格式都遵循會話描述協議,簡稱。 博客原文地址 建議看這篇之前先看一下使用WebRTC搭建前端視頻聊天室——入門篇 如果需要搭建實例的話可以參照SkyRTC-demo:github地址 其中使用了兩個庫:SkyRTC(github地址)和SkyRTC-client(github地址) ...
摘要:本質上允許網頁程序創建點對點通信,我們將會在隨后的章節中進行介紹。信令涉及網絡檢索和穿透,會話創建及管理,通信安全,媒體功能元數據和調制及錯誤處理。這樣就會完全建立及激活節點間的網絡套接字會話。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 這是 JavaScript 工作原理第十八章。 概述 何為 WebRTC ?首先,字面上已經...
閱讀 795·2019-08-30 15:54
閱讀 439·2019-08-30 12:51
閱讀 2021·2019-08-29 16:28
閱讀 2841·2019-08-29 16:10
閱讀 2330·2019-08-29 14:21
閱讀 409·2019-08-29 14:09
閱讀 2126·2019-08-23 16:13
閱讀 1235·2019-08-23 13:59