我会跟踪数组中连接的每个用户的列表。 因此,如果有新的连接,它将检查用户是否已经在列表中,如果他已经在列表中,然后在列表中分配他们的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'由服务器发出。
*注意:主要用户首先登录,然后是双用户。因此,主用户信息直接保存在阵列中,而子用户socket.id则分配了主用户socket.id
[更新]
B2 socket.id分配了B1 socket.id,io.emit for chat工作完美,而io.emit for disconnect只发送给All,除了双用户(B2)
答案 0 :(得分:7)
socket.id
作为自己的套接字列表。你无法覆盖它,或者你破坏了维护自己数据结构的能力。
您有两种选择:
socket.id
值(不会覆盖它),这样您就不会破坏现有行为。它已经保证在服务器上是唯一的。socket.userId
,然后您就不会发生冲突。如果需要,您可以在自己的自定义ID和socket.io socket.id
之间维护一个映射,这样您就可以从另一个中找到一个映射。
答案 1 :(得分:2)
io.engine
对象的generateId prop可用于设置自定义ID。
使用这种方式,可以在服务器端创建所有套接字ID而不会出现任何问题。
实际上我今天写了一篇类似问题的an answer。
一个例子:
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 } }
似乎已经处理好了。
必须记住,套接字ID必须是不可预测的,并且考虑到安全性和应用操作的唯一价值!
额外:由于您socket.id
方法的流程过于紧张,undefined
被generateId
返回,async/await
组合可用于在node.js
版本7.6.0及更高版本上克服了此问题。 handshake
文件的node_modules/engine.io/lib/server.js
方法应更改如下:
<强>前者:强>
Server.prototype.handshake = function (transportName, req) {
var id = this.generateId(req);
...
}
新:
Server.prototype.handshake = async function (transportName, req) {
var id = await this.generateId(req);
...
}