摘要:為了體現前后端分離,提高開發效率的精髓。轉發消息服務器將收到的來自于發送方消息中的值作為要轉發的目標接收方,在服務器自身維護的對象中找到接收方的這個連接,然后將發送方的標識作為轉發給接收方。
背景
簡單的描述一下需求場景:應用需要進行客戶端到客戶端的通信,websocket 就能很好的進行這一操作,目前 網易云信的 IM 等功能也是利用 websocket 進行的。
必要性對前端開發人員來說,目前能夠提供 mock 服務的第三方工具還是比較多的,基本上,與后臺開發人員約定好請求路徑、請求字段和響應字段之后就能前后臺獨立開發了。
但 websocket 服務器與 http 服務器最大的區別就是 websocket 服務器必須得一直提供服務,否則客戶端之間就無法進行通信。
為了體現前后端分離,提高開發效率的精髓。肯定是不能先把邏輯全部盲寫好了之后再與后臺聯調的,便決定與后臺約定好了接口名和數據形式之后,用 nodejs 寫一個簡單的 websocket 通信服務。
功能websocket 用的比較多的應該就是傳輸文本(簡單點說就是字符串),所以,這個字符串攜帶著接收方的用戶標識(toId),其他的信息(比如消息類型 type 和 消息內容 data 等),通常的做法是 JSON.stringfy() 之后轉成字符串,服務端將發送方的用戶標識(fromId)、其他的信息(比如發送過來的消息類型 type 和 消息內容 data)等信息轉發給接收方,接收方接收到字符串之后再 JSON.parse() 進行下一步操作。
用下面這張圖描述一下我希望 websocket 服務器能提供給客戶端的功能。
客戶端websocket 提供的方法中常用的有:new、onopen、onclose、onerror、onmessage、send
毫無疑問,對前端開發人員來說需要與業務邏輯相結合、重點關注的方法就是以下三個:
new在連接 websocket 服務器時傳遞自己的 id
const ws = new WebSocket(`ws://localhost:8080/websocketServer/${id}`);send
發送消息(字符串)給服務器,服務器再轉發給目標
const msgObj = { toId: 666, type: "hello", data: "message......" }; const msgStr = JSON.stringfy(msgObj); ws.send(msgStr);sendTo
由于 send 不能接收對象或者數組類型的數據,每次都得寫一個臨時的對象,再調用 JSON.stringfy() 方法轉成字符串。
那就封裝一個符合自己業務場景的方法,簡化開發過程中實現發送功能的步驟。
// 在原型對象上增加的 sendTo 方法 if ( ! WebSocket.prototype.sendTo ) { WebSocket.prototype.sendTo = function(toId, type, data) { const msg = JSON.stringify({ toId, type, data }); this.send(msg); } } // 調用形式 ws.sendTo(toId, type, data);onmessage
接收消息,通常會根據消息中 type 的不同值:
自己做點什么
給對方一個響應(調用 sendTo 方法)
ws.onmessage = function(msg) { const { fromId, type, data } = JSON.parse(msg); switch (type) { case "message": // 自己做點什么 break; case "hello": // 返回一個消息 this.sendTo(fromId, "response", "response data"); } }
最后簡單的封裝一下初始化方法,方便在不同的地方使用。
const wsUrl = "ws://localhost:8080/"; const wsPath = "socketServer/"; // 生成實例 let ws = null; const connect = async () => { ws = await connectWS(uid, messageHandle); // ... // ... // 連接成功之后做點什么 } function connectWS(uid, msgHandle) { if ( ! WebSocket.prototype.sendTo ) { WebSocket.prototype.sendTo = function(toId, type, data) { const msg = JSON.stringify({ toId, type, data }); this.send(msg); } } return new Promise((resolve, reject) => { const ws = new WebSocket(`${wsUrl}${wsPath}${uid}`); ws.onopen = () => { console.log("open"); resolve(ws); }; ws.onclose = () => { console.log("close"); }; ws.onerror = () => { console.log("error"); }; ws.onmessage = (msg) => { msgHandle(JSON.parse(msg.data)); }; }); } // 接收消息的處理函數 function messageHandle(msgData) { const { fromId, type, data } = msgData; switch (type) { case "": break; default: break; } }服務端
常用的 nodejs-websocket 和 express-ws 兩個框架,都需要自身維護一個對象來記錄每個 websocket 連接是哪個用戶,從而實現消息轉發。
以 express-ws 為例:
記錄連接首先,服務端要記錄當前連接的用戶,以便轉發消息的時候能夠正確發送給目標。
轉發消息服務器將收到的來自于發送方消息中的 toId 值作為要轉發的目標(接收方),在服務器自身維護的對象中找到接收方的這個連接,然后將發送方的標識作為 fromId 轉發給接收方。
const express = require("express"); const express_ws = require("express-ws"); const app = express(); const wsObj = {}; express_ws(app); app.ws("/socketServer/:uid", (ws, req) => { const uid = req.params.uid; wsObj[uid] = ws; ws.onmessage = (msg) => { let { toId, type, data} = JSON.parse(msg.data); const fromId = uid; if (fromId != toId && wsObj[toId]) { // wsObj[toId] 表示 接收方 與服務器的那條連接 // wsObj[fromId] 表示 發送方 與服務器的那條連接 wsObj[toId].send(JSON.stringify( { fromId, type, data } )) } } }); app.listen(8080);
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106307.html
摘要:流控制通常就是在客戶端的頁面使用一個隱藏的窗口向服務端發出一個長連接的請求。和長鏈接以上幾種服務器推的技術中長輪詢和流控制其實都是基于長鏈接來實現的,也就是中所謂的。通信協議于年被定為標準,并被所補充規范。 初探WebSocket node websocket socket.io 我們平常開發的大部分web頁面都是主動‘拉’的形式,如果需要更新頁面內容,則需要刷新一個,但Slack工...
摘要:好的,這樣以來我們的前期準備工作就已經完成了,下面我們來搭建聊天室對應的客戶端和服務器端。 websocket簡介 websocket其實HTML中新增加的內容,其本質還是一種網絡通信協議,以下是websocket的一些特點: (1)因為連接在端口80(ws)或者443(wss)上創建,與HTTP使用的端口相同,幾乎所有的防火墻都不會阻塞WebSocket鏈接 (2)因...
摘要:好的,這樣以來我們的前期準備工作就已經完成了,下面我們來搭建聊天室對應的客戶端和服務器端。 websocket簡介 websocket其實HTML中新增加的內容,其本質還是一種網絡通信協議,以下是websocket的一些特點: (1)因為連接在端口80(ws)或者443(wss)上創建,與HTTP使用的端口相同,幾乎所有的防火墻都不會阻塞WebSocket鏈接 (2)因...
閱讀 1446·2021-09-10 11:27
閱讀 2401·2019-08-30 15:53
閱讀 1317·2019-08-30 13:10
閱讀 2969·2019-08-30 11:09
閱讀 1075·2019-08-29 17:23
閱讀 664·2019-08-29 17:05
閱讀 2943·2019-08-29 15:10
閱讀 2339·2019-08-29 13:22