成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

在 nodejs 中 利用 websocket 實(shí)現(xiàn)簡(jiǎn)單的 “1對(duì)1” 消息傳遞

NoraXie / 2733人閱讀

摘要:為了體現(xiàn)前后端分離,提高開發(fā)效率的精髓。轉(zhuǎn)發(fā)消息服務(wù)器將收到的來(lái)自于發(fā)送方消息中的值作為要轉(zhuǎn)發(fā)的目標(biāo)接收方,在服務(wù)器自身維護(hù)的對(duì)象中找到接收方的這個(gè)連接,然后將發(fā)送方的標(biāo)識(shí)作為轉(zhuǎn)發(fā)給接收方。

背景

簡(jiǎn)單的描述一下需求場(chǎng)景:應(yīng)用需要進(jìn)行客戶端到客戶端的通信,websocket 就能很好的進(jìn)行這一操作,目前 網(wǎng)易云信的 IM 等功能也是利用 websocket 進(jìn)行的。

必要性

對(duì)前端開發(fā)人員來(lái)說(shuō),目前能夠提供 mock 服務(wù)的第三方工具還是比較多的,基本上,與后臺(tái)開發(fā)人員約定好請(qǐng)求路徑、請(qǐng)求字段和響應(yīng)字段之后就能前后臺(tái)獨(dú)立開發(fā)了。

但 websocket 服務(wù)器與 http 服務(wù)器最大的區(qū)別就是 websocket 服務(wù)器必須得一直提供服務(wù),否則客戶端之間就無(wú)法進(jìn)行通信。

為了體現(xiàn)前后端分離,提高開發(fā)效率的精髓??隙ㄊ遣荒芟劝堰壿嬋棵懞昧酥笤倥c后臺(tái)聯(lián)調(diào)的,便決定與后臺(tái)約定好了接口名和數(shù)據(jù)形式之后,用 nodejs 寫一個(gè)簡(jiǎn)單的 websocket 通信服務(wù)。

功能

websocket 用的比較多的應(yīng)該就是傳輸文本(簡(jiǎn)單點(diǎn)說(shuō)就是字符串),所以,這個(gè)字符串?dāng)y帶著接收方的用戶標(biāo)識(shí)(toId),其他的信息(比如消息類型 type 和 消息內(nèi)容 data 等),通常的做法是 JSON.stringfy() 之后轉(zhuǎn)成字符串,服務(wù)端將發(fā)送方的用戶標(biāo)識(shí)(fromId)、其他的信息(比如發(fā)送過(guò)來(lái)的消息類型 type 和 消息內(nèi)容 data)等信息轉(zhuǎn)發(fā)給接收方,接收方接收到字符串之后再 JSON.parse() 進(jìn)行下一步操作。

用下面這張圖描述一下我希望 websocket 服務(wù)器能提供給客戶端的功能。

客戶端

websocket 提供的方法中常用的有:new、onopen、onclose、onerroronmessage、send

毫無(wú)疑問(wèn),對(duì)前端開發(fā)人員來(lái)說(shuō)需要與業(yè)務(wù)邏輯相結(jié)合、重點(diǎn)關(guān)注的方法就是以下三個(gè):

new

在連接 websocket 服務(wù)器時(shí)傳遞自己的 id

const ws = new WebSocket(`ws://localhost:8080/websocketServer/${id}`);
send

發(fā)送消息(字符串)給服務(wù)器,服務(wù)器再轉(zhuǎn)發(fā)給目標(biāo)

const msgObj = {
    toId: 666,
    type: "hello",
    data: "message......"
};
const msgStr = JSON.stringfy(msgObj);
ws.send(msgStr);
sendTo

由于 send 不能接收對(duì)象或者數(shù)組類型的數(shù)據(jù),每次都得寫一個(gè)臨時(shí)的對(duì)象,再調(diào)用 JSON.stringfy() 方法轉(zhuǎn)成字符串。

那就封裝一個(gè)符合自己業(yè)務(wù)場(chǎng)景的方法,簡(jiǎn)化開發(fā)過(guò)程中實(shí)現(xiàn)發(fā)送功能的步驟。

// 在原型對(duì)象上增加的 sendTo 方法
if ( ! WebSocket.prototype.sendTo ) {
    WebSocket.prototype.sendTo = function(toId, type, data) {
        const msg = JSON.stringify({ toId, type, data });
        this.send(msg);
    }
}

// 調(diào)用形式
ws.sendTo(toId, type, data);
onmessage

接收消息,通常會(huì)根據(jù)消息中 type 的不同值:

自己做點(diǎn)什么

給對(duì)方一個(gè)響應(yīng)(調(diào)用 sendTo 方法)

ws.onmessage = function(msg) {
    const { fromId, type, data } = JSON.parse(msg);
    switch (type) {
        case "message":
            // 自己做點(diǎn)什么
            break;
        
        case "hello":
            // 返回一個(gè)消息
            this.sendTo(fromId, "response", "response data");
    }
}

最后簡(jiǎn)單的封裝一下初始化方法,方便在不同的地方使用。

const wsUrl = "ws://localhost:8080/";
const wsPath = "socketServer/";
// 生成實(shí)例
let ws = null;
const connect = async () => {
    ws = await connectWS(uid, messageHandle);
    // ...
    // ...
    // 連接成功之后做點(diǎn)什么
}

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));
        };
    });
}
// 接收消息的處理函數(shù)
function messageHandle(msgData) {
    const { fromId, type, data } = msgData;
    switch (type) {
        case "":
            break;
        default:
            break;
    }
}
服務(wù)端

常用的 nodejs-websocketexpress-ws 兩個(gè)框架,都需要自身維護(hù)一個(gè)對(duì)象來(lái)記錄每個(gè) websocket 連接是哪個(gè)用戶,從而實(shí)現(xiàn)消息轉(zhuǎn)發(fā)。

express-ws 為例:

記錄連接

首先,服務(wù)端要記錄當(dāng)前連接的用戶,以便轉(zhuǎn)發(fā)消息的時(shí)候能夠正確發(fā)送給目標(biāo)。

轉(zhuǎn)發(fā)消息

服務(wù)器將收到的來(lái)自于發(fā)送方消息中的 toId 值作為要轉(zhuǎn)發(fā)的目標(biāo)(接收方),在服務(wù)器自身維護(hù)的對(duì)象中找到接收方的這個(gè)連接,然后將發(fā)送方的標(biāo)識(shí)作為 fromId 轉(zhuǎn)發(fā)給接收方。

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]   表示 接收方 與服務(wù)器的那條連接
            // wsObj[fromId] 表示 發(fā)送方 與服務(wù)器的那條連接
            wsObj[toId].send(JSON.stringify( { fromId, type, data } ))
        }
    }
});

app.listen(8080);

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/106307.html

相關(guān)文章

  • 那些年曾談起跨域

    摘要:在中,在不同的域名下面進(jìn)行數(shù)據(jù)交互,就會(huì)遇到跨域問(wèn)題,說(shuō)到跨域首先要從同源說(shuō)起,瀏覽器為了提供一種安全的運(yùn)行環(huán)境,各個(gè)瀏覽器廠商協(xié)定使用同源策略。在上面說(shuō)過(guò)是不受同源策略限制的,但是出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源請(qǐng)求。 對(duì)于前端開發(fā)來(lái)說(shuō)跨域應(yīng)該是最不陌生的問(wèn)題了,無(wú)論是開發(fā)過(guò)程中還是在面試過(guò)程中都是一個(gè)經(jīng)常遇到的一個(gè)問(wèn)題,在開發(fā)過(guò)程中遇到這個(gè)問(wèn)題的話一般都是找后端同學(xué)去解決...

    galois 評(píng)論0 收藏0
  • 初探WebSocket

    摘要:流控制通常就是在客戶端的頁(yè)面使用一個(gè)隱藏的窗口向服務(wù)端發(fā)出一個(gè)長(zhǎng)連接的請(qǐng)求。和長(zhǎng)鏈接以上幾種服務(wù)器推的技術(shù)中長(zhǎng)輪詢和流控制其實(shí)都是基于長(zhǎng)鏈接來(lái)實(shí)現(xiàn)的,也就是中所謂的。通信協(xié)議于年被定為標(biāo)準(zhǔn),并被所補(bǔ)充規(guī)范。 初探WebSocket node websocket socket.io 我們平常開發(fā)的大部分web頁(yè)面都是主動(dòng)‘拉’的形式,如果需要更新頁(yè)面內(nèi)容,則需要刷新一個(gè),但Slack工...

    Channe 評(píng)論0 收藏0
  • Node.js+WebSocket創(chuàng)建簡(jiǎn)單聊天室

    摘要:好的,這樣以來(lái)我們的前期準(zhǔn)備工作就已經(jīng)完成了,下面我們來(lái)搭建聊天室對(duì)應(yīng)的客戶端和服務(wù)器端。 websocket簡(jiǎn)介 websocket其實(shí)HTML中新增加的內(nèi)容,其本質(zhì)還是一種網(wǎng)絡(luò)通信協(xié)議,以下是websocket的一些特點(diǎn): (1)因?yàn)檫B接在端口80(ws)或者443(wss)上創(chuàng)建,與HTTP使用的端口相同,幾乎所有的防火墻都不會(huì)阻塞WebSocket鏈接 (2)因...

    cppprimer 評(píng)論0 收藏0
  • Node.js+WebSocket創(chuàng)建簡(jiǎn)單聊天室

    摘要:好的,這樣以來(lái)我們的前期準(zhǔn)備工作就已經(jīng)完成了,下面我們來(lái)搭建聊天室對(duì)應(yīng)的客戶端和服務(wù)器端。 websocket簡(jiǎn)介 websocket其實(shí)HTML中新增加的內(nèi)容,其本質(zhì)還是一種網(wǎng)絡(luò)通信協(xié)議,以下是websocket的一些特點(diǎn): (1)因?yàn)檫B接在端口80(ws)或者443(wss)上創(chuàng)建,與HTTP使用的端口相同,幾乎所有的防火墻都不會(huì)阻塞WebSocket鏈接 (2)因...

    Seay 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<