WebSocket
協議能夠實現先後端全雙工通訊,從而取代浪費資源的長輪詢。在此協議的基礎上,能夠實現先後端數據、多端數據,真正的 實時響應。在學習WebSocket
的過程當中,實現了一個簡化版羣聊,過程和代碼詳細記錄在這篇文章中。
本篇文章來自董沅鑫的我的網站,引用、轉載請指明出處。javascript
查看更多知識,或者技術交流:請訪問godbmw.com
css
瞭解計算機網絡協議的人,應該都知道:HTTP 協議是一種無狀態的、無鏈接的、單向的應用層協議。它採用了請求/響應模型。通訊請求只能由客戶端發起,服務端對請求作出應答處理。html
這種通訊模型有一個弊端:HTTP 協議沒法實現服務器主動向客戶端發起消息。java
所以,若是在客戶端想實時監聽服務器變化,必須使用 ajax 來進行輪詢,效率低,浪費資源。node
而 websocket 就可使得先後端進行全雙工通訊(兩方均可以向對方進行數據推送),是真正的平等對話。jquery
支持HTML5
的瀏覽器支持 WebSocket 協議:git
var ws = new WebSocket(url); // 建立一個websocket對象
屬性 | 描述 |
---|---|
ws.readyState | 只讀屬性 readyState 表示鏈接狀態,能夠是如下值:0 - 表示鏈接還沒有創建。1 - 表示鏈接已創建,能夠進行通訊。2 - 表示鏈接正在進行關閉。3 - 表示鏈接已經關閉或者鏈接不能打開。 |
ws.bufferedAmount | 只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,可是尚未發出的 UTF-8 文本字節數。 |
屬性 | 描述 |
---|---|
ws.send() | 數據發送 |
ws.close() | 關閉鏈接 |
屬性 | 描述 |
---|---|
open | 鏈接創建觸發 |
message | 通訊時觸發 |
error | 出錯觸發 |
close | 關閉鏈接觸發 |
假設咱們在本地8080
端口打開了websocket服務,那麼,下面代碼能夠在瀏覽器中實現和這個服務的通訊:github
<body> <script> var ws = new WebSocket("ws://localhost:8080/"); // 創建鏈接觸發 ws.onopen = function () { ws.send("open ws"); console.log("open ws"); }; // 接收服務端數據觸發 ws.onmessage = function (evt) { var data = evt.data; console.log("Data is ", data); }; // 斷開鏈接觸發 ws.onclose = function () { console.log("close ws"); }; </script> </body>
關於服務端實現,根據技術選型不一樣,能夠選用不一樣的庫和包。我這裏使用的是node
的ws
庫來websocket服務端。
在阮一峯的博文提到的socket.io
庫,在瀏覽器端的寫法不兼容原生API,準確來講,它們本身實現了一套websocket。因此,使用的時候先後端都應該引用第三方庫。這樣就形成了代碼遷移性,嚴重降低。web
綜上所述,ws
庫有如下優勢:ajax
首先,在命令行中,安裝ws
庫: npm install ws --save
如今,利用ws
來實現一個監聽8080
端口的websocket服務器,講解都在代碼註釋裏,一目瞭然:
const PORT = 8080; // 監聽端口 const WebSocket = require("ws"); // 引入 ws 庫 const wss = new WebSocket.Server({ port: PORT }); // 聲明wss對象 /** * 向除了自己以外全部客戶端發送消息,實現羣聊功能 * @param {*} data 要發送的數據 * @param {*} ws 客戶端鏈接對象 */ wss.broadcastToElse = function broadcast(data, ws) { wss.clients.forEach(function each(client) { if (client !== ws && client.readyState === WebSocket.OPEN) { client.send(data); } }); }; /* 客戶端接入,觸發 connection */ wss.on("connection", function connection(ws, req) { let ip = req.connection.remoteAddress; // 經過req對象能夠得到客戶端信息,好比:ip,headers等 /* 客戶端發送消息,觸發 message */ ws.on("message", function incoming(message) { ws.send(message); // 向客戶端發送消息 wss.broadcastToElse(message, ws); // 向 其餘的 客戶端發送消息,實現羣聊效果 }); });
爲了方便編寫,這裏引入了jquery
和bootstrap
這兩個庫,只須要關注js代碼便可。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>羣聊</title> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.min.js"></script> </head> <body> <div class="container"> <textarea class="form-control" rows="30" disabled="disabled" id="show-area"></textarea> <input type="text" class="form-control" placeholder="請輸入聊天內容" id="chat-input"> <button type="button" class="btn btn-info" id="send-btn">發送</button> </div> <script> var userName = parseInt(Math.random() * 1000, 10) // 隨機用戶名, 以標識身份 var sendBtn = $("#send-btn"), // 發送信息按鈕 chatInput = $("#chat-input"), // 聊天信息輸入框 showArea = $("#show-area") // 聊天信息展現框 var ws = new WebSocket("ws://localhost:8080/") // 初始化WebSocket對象 sendBtn.on("click", function () { var content = chatInput.val() if (content.length === 0) { return alert("請不要輸入空白內容") } content = "At " + (new Date()).toString() + "\n" + "來自用戶" + userName + "\n" + content // 拼接用戶信息、時間信息和消息 ws.send(content) // 發送消息 chatInput.val("") // 清空輸入框 }) ws.onopen = function () { console.log("Conncet open") } ws.onmessage = function (evt) { var data = evt.data showArea.val(showArea.val() + data + "\n\n") // 刷新聊天信息展現框:顯示羣聊信息 } ws.onclose = function () { console.log("Connect close") } </script> </body> </html>
首先啓動咱們的服務端代碼:node server.js
。其中,server.js
是放置服務端代碼的文件。
而後,咱們打開2次編寫的html
代碼,這至關於,打開2個客戶端。來檢測羣聊功能。
概念解釋:
ws
文檔:https://www.npmjs.com/package/ws 本篇文章來自董沅鑫的我的網站,引用、轉載請指明出處。
查看更多知識,或者技術交流:請訪問godbmw.com