websocket學習和羣聊實現

> `WebSocket`協議可以實現前後端全雙工通信,從而取代浪費資源的長輪詢。在此協議的基礎上,可以實現前後端數據、多端數據,真正的**實時響應**。在學習`WebSocket`的過程中,實現了一個簡化版羣聊,過程和代碼詳細記錄在這篇文章中。 **本篇文章來自[董沅鑫的個人網站](https://godbmw.com/passage/38),引用、轉載請指明出處**。 **查看更多知識,或者技術交流:請訪問[`godbmw.com`](https://godbmw.com/)** ## 1 概述 ### 1.1 WebSocket 是什麼? 1. 建立在 TCP 協議之上的網絡通信協議 2. 全雙工通信協議 3. 沒有同源限制 4. 可以發送文本、二進制數據等 ### 1.2 爲什麼需要 WebSocket? 瞭解計算機網絡協議的人,應該都知道:HTTP 協議是一種無狀態的、無連接的、單向的應用層協議。它採用了請求/響應模型。通信請求只能由客戶端發起,服務端對請求做出應答處理。 這種通信模型有一個弊端:HTTP 協議無法實現服務器主動向客戶端發起消息。 因此,如果在客戶端想實時監聽服務器變化,必須使用 ajax 來進行輪詢,效率低,浪費資源。 而 websocket 就可以使得**前後端進行全雙工通信(兩方都可以向對方進行數據推送),是真正的平等對話**。 ## 2 WebSocket 客戶端 支持`HTML5`的瀏覽器支持 WebSocket 協議: ```javascript var ws = new WebSocket(url); // 創建一個websocket對象 ``` ### 2.1 WebSocket 屬性 | 屬性 | 描述 | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ws.readyState | 只讀屬性 readyState 表示連接狀態,可以是以下值:0 - 表示連接尚未建立。1 - 表示連接已建立,可以進行通信。2 - 表示連接正在進行關閉。3 - 表示連接已經關閉或者連接不能打開。 | | ws.bufferedAmount | 只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,但是還沒有發出的 UTF-8 文本字節數。 | ### 2.2 WebSocket 方法 | 屬性 | 描述 | | ---------- | -------- | | ws.send() | 數據發送 | | ws.close() | 關閉連接 | ### 2.3 Websocket 事件 | 屬性 | 描述 | | ------- | ------------ | | open | 連接建立觸發 | | message | 通信時觸發 | | error | 出錯觸發 | | close | 關閉連接觸發 | ### 2.4 代碼實現 假設我們在本地`8080`端口打開了websocket服務,那麼,下面代碼可以在瀏覽器中實現和這個服務的通信: ```html ``` ## 3 WebSocket 服務端 > 關於服務端實現,根據技術選型不同,可以選用不同的庫和包。我這裏使用的是`node`的`ws`庫來websocket服務端。 在[阮一峯的博文](http://www.ruanyifeng.com/blog/2017/05/websocket.html)提到的`socket.io`庫,在瀏覽器端的寫法不兼容原生API,準確來說,它們自己實現了一套websocket。所以,使用的時候前後端都應該引用第三方庫。**這樣就造成了代碼遷移性,嚴重下降。** 綜上所述,`ws`庫有以下優點: 1. 兼容性好,兼容瀏覽器原生API 2. 長期維護,效果穩定 3. 使用方便(往下看就知道了) ## 4 實現羣聊 ### 4.1 羣聊 服務端實現 首先,在命令行中,安裝`ws`庫: `npm install ws --save` 現在,利用`ws`來實現一個監聽`8080`端口的websocket服務器,**講解都在代碼註釋裏,一目瞭然**: ```javascript 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); // 向 其他的 客戶端發送消息,實現羣聊效果 }); }); ``` ### 4.2 羣聊 客戶端實現 爲了方便編寫,這裏引入了`jquery`和`bootstrap`這兩個庫,只需要關注js代碼即可。 ```html

羣聊
``` ### 4.3 羣聊 效果展示 首先啓動我們的服務端代碼:`node server.js` 。其中,`server.js`是放置服務端代碼的文件。 然後,我們打開2次編寫的`html`代碼,這相當於,打開2個客戶端。來檢測羣聊功能。 ![效果圖](https://raw.githubusercontent.com/dongyuanxin/markdown-static/master/JavaScript/websocket學習和羣聊實現/1.png) ## 5. 相關資料 - 概念解釋: - http://www.ruanyifeng.com/blog/2017/05/websocket.html - https://www.cnblogs.com/jingmoxukong/p/7755643.html - `ws`文檔:https://www.npmjs.com/package/ws **本篇文章來自[董沅鑫的個人網站](https://godbmw.com/passage/38),引用、轉載請指明出處**。 **查看更多知識,或者技術交流:請訪問[`godbmw`](https://godbmw.com/)**
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章