简体   繁体   English

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

[英]Manage multiple tabs (but same user) in socket.io

I'm having some problems with socket.io, and I have no idea how to solve it. 我有一些socket.io的问题,我不知道如何解决它。 I've an app with a login system with socket.io to manage user interactions. 我有一个带有socket.io的登录系统的应用程序来管理用户交互。 Also I've an array to manage all active websocket sessions. 我还有一个数组来管理所有活动的websocket会话。 This array stores a pair session.id => username. 此数组存储一对session.id => username。

Problems begin when a user opens a new tab with the same page (or a different page that uses the websocket). 当用户打开具有相同页面的新选项卡(或使用websocket的不同页面)时,问题就开始了。 This cause a duplicate username entry in the array. 这会导致数组中的用户名条目重复。

{id1, username}
{id2, username}

When socket sends a message to the user, it sends only to the first session id of the array, so only one tab receives the message. 当套接字向用户发送消息时,它仅发送到该阵列的第一个会话ID,因此只有一个选项卡接收该消息。

I've tried to change the socket id of the new connection to match the other, but it doesn't work. 我试图更改新连接的套接字ID以匹配另一个,但它不起作用。

socket.id = sessionId of the other websocket;

I think another solution is to send the message to all the open sessions, but I think it's not the best way to do that. 我认为另一个解决方案是将消息发送到所有打开的会话,但我认为这不是最好的方法。

Thanks. 谢谢。

It sounds like you may be referring to the socket id in your question, not the session id. 听起来你可能是指你问题中的套接字ID,而不是会话ID。 If you have an express session you can use the session id, which will be the same regardless of how many tabs are open as long as they use the same browser and it's not in "private" mode. 如果您有快速会话,则可以使用会话ID,无论打开多少个选项卡,只要它们使用相同的浏览器并且它不处于“私有”模式,它就会相同。 Take a look at this question for how to enable sessions in socket.io. 看看这个问题,了解如何在socket.io中启用会话。

socket.io and session? socket.io和session?

Update: When you're saving the session id, you'll associate it with the user's nickname and the connected sockets. 更新:当您保存会话ID时,您将其与用户的昵称和连接的套接字关联。 Then you can iterate through each socket and send the message. 然后,您可以遍历每个套接字并发送消息。 Something like the following: 类似于以下内容:

[
    {sessionId: '12345', nickname: 'timmay!', socketIds: [1, 2, 3]},
    {sessionId: '23456', nickname: 'pete', socketIds: [4, 5, 6]}
]

When another connection is established you push the new socket id into the socketIds array, and when a user disconnects you remove the id. 建立另一个连接时,将新的套接字ID推入socketIds数组,当用户断开连接时,删除id。

Another option might be to only allow one tab per user per session. 另一个选项可能是每个会话仅允许每个用户使用一个选项卡。 You can store a single socketId and when a new socket connects for the same user, you can disconnect the original socket and use the new one instead. 您可以存储单个socketId,当新套接字连接到同一用户时,您可以断开原始套接字并使用新套接字。

You can use hash like that: 您可以使用这样的哈希:

var sessionHash = {};
sessionHash['userName'] = socket;

and check on io.sockets.on('connection',..) whether a socket exist under that key. 并检查io.sockets.on('connection',..)是否存在该键下的套接字。

If it does, you can execute sessionHash['userName'].disconnect(); 如果是,则可以执行sessionHash['userName'].disconnect(); on it and save the brand new socket. 在它上面并保存全新的插座。

I know it has been a long time since you asked this, but Just 4 ago I published a module for node js, express and socket.io which manages that exactly thing you wanted. 我知道你问这个问题已经有很长一段时间了,但就在4年前我发布了一个节点js,express和socket.io的模块,它管理着你想要的东西。 Check the Usage and Example, I hope you will find this module helpful! 查看用法和示例,希望您会发现此模块有用!

You can install it via NPM socket.io.users This is a node js module for socket.io applications. 您可以通过NPM socket.io.users安装它。这是socket.io应用程序的节点js模块。 One user per client. 每个客户一个用户。

Some of the usage code 一些使用代码

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..

Intercom library can be used to share and manage a socket.io connection. 内部通信库可用于共享和管理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!'
});

You could also use socketio shared webworkers 您也可以使用socketio共享的webworkers

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM