簡體   English   中英

socket.io 分配自定義 socket.id

[英]socket.io assigning custom socket.id

我跟蹤陣列中連接的每個用戶的列表。 所以如果有一個新的連接,它會檢查用戶是否已經在列表中,如果他已經在列表中,那么將他們的socket.id分配給列表中對應的socket.id,否則就添加他們到列表中。

這是為了防止同一用戶在嘗試進行多次登錄時被計為 2 個用戶。

Object.keys(client).forEach(function (key) {
    if (client[key].id == data.id){
        is_connected = true;
        socket.id = key;
    }
});

我在處理嘗試多次登錄的用戶發送/接收的消息/聊天時沒有問題。

socket.on('chat', function(msg){
    var data = {"name": client[socket.id].name, "message": msg};
    io.emit('chat', data);
});

聊天消息的 io.emit 已成功發送給嘗試多次登錄的用戶。

我遇到的問題是每當用戶決定從服務器注銷/斷開連接時。

io.emit('user_leave', client[socket.id].id);

[多用戶登錄案例] -> 多用戶和雙用戶是同一用戶嘗試多用戶登錄

每當主用戶與服務器斷開連接時,雙用戶就會收到服務器發送的“user_leave”,因為 io.emit 應該將其發送到所有套接字。

但並非如此,當子用戶與服務器斷開連接時,主用戶不會收到服務器發出的“user_leave”。

*注:主用戶是先登錄,然后是雙用戶。 所以Main-User信息直接保存在數組中,而Sub-User socket.id被分配了Main-User socket.id

[更新]

解釋

B2 socket.id 分配給 B1 socket.id,用於聊天的 io.emit 完美工作,而用於斷開連接的 io.emit 僅發送給除雙用戶(B2)之外的所有用戶

socket.id在 socket.io 內部用於自己的套接字列表。 你不能覆蓋它,或者你破壞了它維護自己的數據結構的一些能力。

你有兩個選擇:

  1. 您可以按原樣使用現有的socket.id值(不覆蓋它),這樣就不會破壞現有的行為。 它已經保證在服務器上是唯一的。
  2. 您可以為自己的 id 使用不同的屬性名稱,例如socket.userId ,這樣就不會發生沖突。

如果需要,您可以維護您自己的自定義 id 和 socket.io socket.id之間的映射,以便您可以從另一個訪問。

類似的問題: Socket.io custom client ID

io.engine對象的generateId屬性可用於設置自定義 id。

使用這種方式,可以在服務器端創建所有套接字 ID,而不會出現任何問題。

其實我今天寫了一個類似問題的答案

一個例子:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

io.engine.generateId = function (req) {
    // generate a new custom id here
    return 1
}


io.on('connection', function (socket) {

    // listing the default namespace rooms
    console.log("rooms: ", io.nsps["/"].adapter.rooms);

})

控制台輸出如下:
rooms: { '/#1': Room { sockets: { '/#1': true }, length: 1 } }

好像已經處理好了。

必須記住,考慮到安全性和應用程序操作,socket id 必須是不可預測的和唯一的值!

額外:如果由於您對generateId方法的密集處理而將socket.id返回為undefined ,則可以使用async/await組合來克服node.js版本 7.6.0 及更高版本上的此問題。
node_modules/engine.io/lib/server.js文件的handshake方法應更改如下:

以前的:

Server.prototype.handshake = function (transportName, req) {
  var id = this.generateId(req);
  ...
}

新的:

Server.prototype.handshake = async function (transportName, req) {
  var id = await this.generateId(req);
  ...
}

我有一個關於這個話題的問題。 我正在制作一個簡單的 react-native 聊天應用程序,我使用 express 和 socket.io 作為后端,使用 mongoDB 作為數據庫。 我要求我的所有用戶都登錄,並檢查他們是否登錄了套接字中間件,允許他們創建連接並僅在登錄時發送消息。 由於我正在使用中間件,並且由於 mongoDB 已經保證它們的 _id 對每個用戶都是唯一的,並且我已經在 J​​WT 中將它們發送到中間件,我可以在創建連接之前將此 id 設置為中間件中的套接字 id 嗎? 我已經嘗試過了,它在 on('connection') 中將正確的 _id 作為 socket.id 進行控制台,但我不知道它以后是否會在此過程中產生更多問題..? 有人知道這個問題的答案嗎?

代碼看起來像:

io.use((socket, next) => {
    if (socket.handshake?.query?.token) {
        jwt.verify(socket.handshake.query.token, process.env.ACCESS_TOKEN_SECRET, (err, decoded) => {
            if (err) return next(new Error('Authentication error'));
            socket.user = decoded.user;
            socket.id = decoded.user.id; // THIS LINE ADDS THE ID
            next();
        })
    } else {
        next(new Error('Authentication error'));
    }
}).on('connection', (socket) => {
    console.log(socket.id); // HERE IT'S THE CORRECT MONGODB ID
    ...
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM