[WebRTC] 透過 WebRTC 做到P2P對談(1) – Server篇
接下來幾篇文章,我想實作一下WebRTC來做到P2P對談,基本上我是接到任務發現這真的是一個有點小複雜的東西,所以網路上看一些文章測試出不少方法,這是目前跑起來看起來比較容易懂的方法,介紹給大家讓大家少走一些冤枉路,首先這邊我們要用到的東西,分別為兩台電腦(分別在不同IP),然後一台Linux的機器,另一台我是用Windows ,為何要用Linux因為跑node.js 我主要都是用Linux ,不過你可以自己重組你自己的環境,這一篇主要是基本概念+Signaling Server 的建置.. HERE WE GO !!
1.什麼是WebRTC: WebRTC,名稱源自網頁即時通訊(英語:Web Real-Time Communication)的縮寫,是一個支援網頁瀏覽器進行實時語音對話或影片對話的API。它於2011年6月1日開源並在Google、Mozilla、Opera支援下被納入全球資訊網協會的W3C推薦標準[1][2][3]。 (from : https://zh.wikipedia.org/wiki/WebRTC)
簡單的說一個技術用來做到瀏覽器之間來做到P2P的溝通。
2.為何還要架設Server ,因為茫茫人海中,你要如何讓兩個瀏覽器知道對方,所以需要一台Singaling Server來做到,目前網路上很多作法用firebase,但是這邊我希望就是用自己的server 所以我選用nodejs來架設websocket 做通訊的signaling server .
簡單的說就是讓兩個client彼此知道存在。
3.你會聽到一個名詞叫做ICE /STUN,網路上說 互動式連結建立 (Interactive Connectivity Establishment,ICE) 是可讓網路瀏覽器連上端點的框架。有很多原因會導致無法建立Peer A 與 Peer B 的直接連線。若連線遭遇到阻擋開放連線的防火牆,可透過 ICE 越過防火牆。在大多數情況下,你的裝置都沒有公用的 IP 位址,也能讓 ICE 提供專屬位址。如果你的路由器無法直接連上端點,同樣能藉由 ICE 讓中介伺服器轉發資料。
STUN :NAT 會話傳輸應用程序 (Session Traversal Utilities for NAT,STUN) (縮寫之內還有縮寫) 屬於一種通訊協定,可找到你的公用位址,並判斷你的路由器是否會限制直接連上端點。用戶端將送出請求到 STUN 伺服器,而 STUN 伺服器會回傳用戶端的公用位址,並藉以得知路由器 NAT 背後的用戶端是否連上公用網路。
(from : https://blog.mozilla.com.tw/posts/3261/webrtc-%E7%9B%B8%E9%97%9C%E7%B8%AE%E5%AF%AB%E5%90%8D%E8%A9%9E%E7%B0%A1%E4%BB%8B)
簡單的說 一種技術讓你在p2p通訊的時候對於許多限制被統一克服的解決方案。
在之後的範例裡面我們是用Google的機器 : stun:stun2.l.google.com:19302
4. 終於我們要開始動作了,首先,你得先安裝node.js 還有 npm 這邊我就不贅述
sudo apt-get update sudo apt-get install nodejs sudo apt-get install npm
5.接下來 就是給你一段code 你就直接存成server.js 並且存檔用node.js run 起來
//require our websocket library var WebSocketServer = require('ws').Server; //creating a websocket server at port 9090 var wss = new WebSocketServer({ port: 9090 }); //all connected to the server users var users = {}; //when a user connects to our sever wss.on('connection', function (connection) { console.log("User connected"); //when server gets a message from a connected user connection.on('message', function (message) { var data; //accepting only JSON messages try { data = JSON.parse(message); } catch (e) { console.log("Invalid JSON"); data = {}; } //switching type of the user message switch (data.type) { //when a user tries to login case "login": console.log("User logged", data.name); //if anyone is logged in with this username then refuse if (users[data.name]) { sendTo(connection, { type: "login", success: false, message: '重複登入' }); } else { //save user connection on the server users[data.name] = connection; connection.name = data.name; sendTo(connection, { type: "login", success: true }); } console.log("users data: ", users); break; case "offer": //for ex. UserA wants to call UserB console.log("Sending offer to: ", data.name); //if UserB exists then send him offer details var conn = users[data.name]; if (conn != null) { //setting that UserA connected with UserB connection.otherName = data.name; sendTo(conn, { type: "offer", offer: data.offer, name: connection.name }); } break; case "answer": console.log("Sending answer to: ", data.name); //for ex. UserB answers UserA var conn = users[data.name]; if (conn != null) { connection.otherName = data.name; sendTo(conn, { type: "answer", answer: data.answer }); } break; case "candidate": console.log("Sending candidate to:", data.name); var conn = users[data.name]; if (conn != null) { sendTo(conn, { type: "candidate", candidate: data.candidate }); } break; case "leave": var conn = users[data.name]; users[data.name]=undefined; //conn.otherName = null; //notify the other user so he can disconnect his peer connection if (conn != null) { sendTo(conn, { type: "leave" }); } console.log("[leave] users data : ", users); break; default: sendTo(connection, { type: "error", message: "Command not found: " + data.type }); break; } }); //when user exits, for example closes a browser window //this may help if we are still in "offer","answer" or "candidate" state connection.on("close", function () { if (connection.name) { delete users[connection.name]; if (connection.otherName) { console.log("Disconnecting from ", connection.otherName); var conn = users[connection.otherName]; if (conn != null) { conn.otherName = null; sendTo(conn, { type: "leave" }); } } } }); connection.send(JSON.stringify({ type: "hello", message: 'Welcome to connect Signaling Server' })); }); function sendTo(connection, message) { connection.send(JSON.stringify(message)); }
6.執行起來 node server.js ,如果你跑起來會出現Error: Cannot find module 'ws' ,你就記得安裝 ws 套件
npm install ws
之後就是run 起來,這樣ws 版本的signaling server就建設好了
這邊有幾件事情要提一下,上面的code不完全是我寫的,是我改網路上看到的code ,因為他的code run 起來可能因為版本關係有些地方不太對,而且我加入些東西,如果你覺得我說的不夠清楚,請您移駕到這裡
https://www.tutorialspoint.com/webrtc/webrtc_text_demo.htm
接下來就是client 得部分
標籤:
Javascript
,
Linux
,
Node.js
-- Yesterday I wrote down the code. I bet I could be your hero. I am a mighty little programmer. 如果這篇文章有幫助到您,簡單留個言,或是幫我按個讚,讓我有寫下去的動力...