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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12166187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:28:48  来源:igfitidea点击:

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

javascriptnode.jssessionsocket.io

提问by Miguel

I'm having some problems with socket.io, and I have no idea how to solve it. I've an app with a login system with socket.io to manage user interactions. Also I've an array to manage all active websocket sessions. This array stores a pair session.id => username.

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

Problems begin when a user opens a new tab with the same page (or a different page that uses the websocket). This cause a duplicate username entry in the array.

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

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

当 socket 向用户发送消息时,它只发送到数组的第一个会话 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.

谢谢。

回答by Timothy Strimple

It sounds like you may be referring to the socket id in your question, not the session 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. Take a look at this question for how to enable sessions in socket.io.

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

socket.io and session?

socket.io 和会话?

Update:When you're saving the session id, you'll associate it with the user's nickname and the connected sockets. Then you can iterate through each socket and send the message. Something like the following:

更新:当您保存会话 ID 时,您会将其与用户的昵称和连接的套接字相关联。然后您可以遍历每个套接字并发送消息。类似于以下内容:

[
    {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,当同一个用户连接新的套接字时,您可以断开原始套接字的连接并改用新的套接字。

回答by ohadinho

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();on it and save the brand new socket.

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

回答by kataras

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. Check the Usage and Example, I hope you will find this module helpful!

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

You can install it via NPM socket.io.usersThis is a node js module for socket.io applications. One user per client.

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

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

回答by StefansArya

Intercom librarycan be used to share and manage a socket.io connection.

Intercom 库可用于共享和管理 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 共享网络工作者