Javascript 在socket.io中管理多个选项卡(但用户相同)

Javascript 在socket.io中管理多个选项卡(但用户相同),javascript,node.js,session,socket.io,Javascript,Node.js,Session,Socket.io,我在socket.io上遇到了一些问题,我不知道如何解决它。我有一个带有socket.io的登录系统的应用程序来管理用户交互。我还有一个数组来管理所有活动的websocket会话。此数组存储一对session.id=>username 当用户打开具有相同页面(或使用websocket的不同页面)的新选项卡时,就会出现问题。这会导致数组中出现重复的用户名条目 {id1, username} {id2, username} 当套接字向用户发送消息时,它只向数组的第一个会话id发送消息,因此只有一个

我在socket.io上遇到了一些问题,我不知道如何解决它。我有一个带有socket.io的登录系统的应用程序来管理用户交互。我还有一个数组来管理所有活动的websocket会话。此数组存储一对session.id=>username

当用户打开具有相同页面(或使用websocket的不同页面)的新选项卡时,就会出现问题。这会导致数组中出现重复的用户名条目

{id1, username}
{id2, username}
当套接字向用户发送消息时,它只向数组的第一个会话id发送消息,因此只有一个选项卡接收消息

我已尝试更改新连接的套接字id以匹配另一个连接,但无效

socket.id = sessionId of the other websocket;
我认为另一个解决办法是向所有公开会议发送信息,但我认为这不是最好的方式


谢谢。

听起来您的问题中可能指的是套接字id,而不是会话id。如果您有快速会话,您可以使用会话id,只要它们使用相同的浏览器且不处于“专用”模式,则无论有多少选项卡打开,会话id都是相同的。看看这个问题,了解如何在socket.io中启用会话

更新: 保存会话id时,将其与用户的昵称和连接的套接字相关联。然后您可以遍历每个套接字并发送消息。如下所示:

[
    {sessionId: '12345', nickname: 'timmay!', socketIds: [1, 2, 3]},
    {sessionId: '23456', nickname: 'pete', socketIds: [4, 5, 6]}
]
当建立另一个连接时,您将新的套接字id推入SocketID阵列,当用户断开连接时,您将删除该id


另一个选项可能是每个会话中每个用户只允许一个选项卡。您可以存储一个socketId,当为同一用户连接一个新套接字时,您可以断开原始套接字并使用新的套接字。

您可以使用如下哈希:

var sessionHash = {};
sessionHash['userName'] = socket;
并检查
io.sockets.on('connection',…)
该键下是否存在套接字


如果有,您可以执行
sessionHash['userName'].disconnect()并保存全新的套接字。

我知道你问这个问题已经很久了,但就在4年前,我发布了一个node js、express和socket.io模块,它管理的正是你想要的东西。检查用法和示例,我希望您会发现此模块很有帮助

您可以通过NPM安装它。这是一个用于socket.io应用程序的node js模块。每个客户端一个用户

一些用法代码

var express = require('express');
var app = express();
var server = require('http').createServer(app);
var socketUsers = require('socket.io.users');
//....
socketUsers.Session(app);//IMPORTANT 
//...
var rootIo = require('socket.io')(server); //default '/' as namespace. 
var chatIo = rootIo.of('/chat');

var rootUsers = socketUsers.Users; /* default '/' as namespace.
Each namespace       has IT's OWN users object list,
but the Id of a user of any other namespace may 
has the same value if       request comes from the same client-machine-user.
This makes   easy to keep a kind of 
synchronization between all users of all   different namespaces. */

var chatUsers = socketUsers.Users.of('/chat'); //  


rootIo.use(socketUsers.Middleware());/*IMPORTANT but no errors if you want
to  skip it for a io.of(namespace) 
that you don't want the socket.io.users' support.  */

chatUsers.use(socketUsers.Middleware());

chatUsers.on('connected',function(user){
console.log(user.id + ' has connected to the CHAT');
user.store.username = 'username setted by server side'; /*at the store
property you can store any type of properties
and objects you want to share between your user's sockets.  */
user.socket.on('any event', function(data){ 
/*user.socket is the current socket, to get all connected sockets from this  
user, use: user.sockets */

});
chatIo.emit('set username',user.store.username);
});

rootUsers.on('connected',function(user){
   console.log('User has connected with ID: '+ user.id);
});



rootUsers.on('connection',function(user){
   console.log('Socket ID: '+user.socket.id+' is user with ID: '+user.id);
});

rootUsers.on('disconnected',function(user){
    console.log('User with ID: '+user.id+'is gone away :(');
});

//...server.listen blabla..
可用于共享和管理socket.io连接

// Initialize socket.io on one tab
var socket = io.connect('//yourwebsite.com/socketio');

// Initialize intercom on all tab
var intercom = Intercom.getInstance();
intercom.bind(socket);

// Listen to an event
intercom.on('msgBroadcast', function(data){
    console.log(data);
});

// Emit an event
intercom.emit('msgBroadcast', {
    socket: true,
    message: 'Hello all!'
});

您也可以使用

谢谢。现在,我已经在socket.io(socket.handshake.sessionID)中找到了会话id,但是我如何才能将消息发送到特定的sessionID,如io.sockets.socket(socketid.emit)(…),但使用sessionID代替socketid?谢谢。我知道了。最后一个问题。可以在没有io.sockets.socket(socketid).emit(…)循环的情况下向套接字ID数组发送消息?是和否。必须有一个循环,但不一定要编写它。您可以使用类似下划线提供的每个函数@Timothy Strimple您使用的是什么websocket服务器?另一种解决方案可能是在每个cookie会话中打开一个套接字,然后通过eventemitter通过本地存储侦听和发送套接字。我按照您的建议做了。我只想为每个连接的用户保留一个活动选项卡。问题是,当我尝试记录旧sessionID(旧选项卡)和新sessionID(刚刚打开的选项卡)时,它们是相同的。我不明白为什么,因为我正在断开旧的socketI尝试您的方法,但是套接字(在第一个选项卡中)与套接字(在第二个选项卡中)不同,我是否做错了什么?模块在哪里?