微信小程式websocket聊天室

極楽發表於2019-02-11

背景

最近做了一個微信小程式的即時通訊功能,之前我也做過node.js的websocket服務,不過是在web端應用的socket.io服務。小程式本身對http、websocket等連線均有諸多限制,所以這次專案選擇了node.js自帶的ws模組。

服務端

初始化一個node.js專案,引入ws模組

const webSocket = require('ws');
複製程式碼

建立websocket例項,並設定監聽埠

const wss = new webSocket.Server({
    port: 3001
});
複製程式碼

定義wss例項方法,實現socket監聽和資訊釋出。下面貼上簡單的示例:

wss.on('connection', function connection(ws, req) {
    console.log('連線開啟')
    
    //發生錯誤
    ws.on('error', function error(error) {
        console.log('error', error);
    });

    //斷開連線
    ws.on('close', function close(close) {
        console.log( '已關閉');
    });

    ws.on('message', function message(message) {
        ws.send('客戶端發來了一條訊息')
    });

    //傳送訊息
    ws.send('連線已開啟');
    ws.send(id + '已連線')
});
複製程式碼

這樣,一個簡單的websocket服務就配置完成了。當然,問題遠遠不止這麼簡單。要想在小程式中進行通訊,還需要解決下面幾個問題。

域名

關於小程式服務端域名配置,小程式開發文件中如下提到

微信小程式websocket聊天室
小程式請求地址只支援https或者wss協議,因此首先要配置的就是SSL證書。拿到SSL證書之後,在服務端做一下https的配置即可。

var fs = require('fs');
const options = {
    key: fs.readFileSync('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'utf8'),//證書地址
    cert: fs.readFileSync('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'utf8'),//證書地址
};
var https = require('https');
var server = https.createServer(options, app);
複製程式碼

另外值得注意的是,websocket監聽的埠號需要做一下代理,因為小程式如果不配置埠號時,所有請求的url都不可以帶埠號。

多房間通訊

先看一下廣播的實現:

//廣播方法
wss.broadcast = function broadcast(data) {
    wss.clients.forEach(function each(client) {
        client.send(data)
    });
};
複製程式碼

wss物件的clients是一個儲存著所有socket連線物件的陣列,每條連線物件都可以呼叫各自的send方法傳送資訊。

在此基礎上,我們可以進行一定的封裝,用一個唯一的識別符號對映到每一條socket連線,這樣我們需要向特定的某個連線傳送資訊時,就可以找到該連線。

可以通過連線的url作為唯一標識:

 let sockets = {}
 wss.on('connection', function connection(ws, req) {
        let id = req.url.slice(5);//截幾位字串根據自己實際獲得的url來看
        sockets[id] = ws;
        ws.send(id + '已連線');
        ...
複製程式碼

客戶端每次連線時url後拼接一個唯一id,在服務端獲取req.url並擷取字串拿到唯一id,並將該連線物件儲存在全域性的sockets下以便需要時使用。

在此基礎上,可以繼續封裝諸如加入房間、離開房間、房間內通訊、向特定使用者私聊等功能,總體來說是對send方法的封裝。值得注意的是send方法只能傳送字串,json物件需要轉化成字串再傳入send。

下面是一個私聊的示例:

wss.notice = function notice(id, data, ws) {
    // 向指定id傳送
    try {
        ws.send('正在傳送...')
        var notice = JSON.stringify({
            type: 'notice',
            data: data
        })
        let target = sockets[id]
        if (target) {
            target.send('收到一條新訊息')
            target.send(notice)
        } else {
            ws.send('目標通道已關閉')
        }
    } catch (err) {
        console.log(err)
    }
}
複製程式碼

到這裡,一個簡單的聊天室服務端配置就基本完成了。

最終作品效果如下:

kafv7R.gif

部分程式碼細節,請觀眾老爺們移步 微信小程式中聊天室的服務端和客戶端配置示例 ^.^

有問題可以一起探討,順手點個贊就更好啦!

相關文章