Node.js 维护与同一用户打开的每个新选项卡的socketio连接

Node.js 维护与同一用户打开的每个新选项卡的socketio连接,node.js,websocket,socket.io,Node.js,Websocket,Socket.io,我正在为我们的网站制作一个应用程序,用户可以在其中相互发送聊天信息。我使用nodejs和socketio成功地做到了这一点。我有一个标题,上面有一些通知图标,就像facebook一样,可以在所有页面中看到。现在,如果用户打开多个选项卡并收到一条消息,那么所有打开的选项卡都会看到图标亮起。我通过跟踪用户通过2D套接字阵列打开的套接字连接来实现这一点: var container = {}; io.sockets.on( 'connection', function(client) { c

我正在为我们的网站制作一个应用程序,用户可以在其中相互发送聊天信息。我使用nodejs和socketio成功地做到了这一点。我有一个标题,上面有一些通知图标,就像facebook一样,可以在所有页面中看到。现在,如果用户打开多个选项卡并收到一条消息,那么所有打开的选项卡都会看到图标亮起。我通过跟踪用户通过2D套接字阵列打开的套接字连接来实现这一点:

var container = {};
io.sockets.on( 'connection', function(client) {

    client.on('set account online', function(username) {
        if (!(username in container)) {
            console.log(username + " is now Online" );
            container[username] = [];
        }
        client.username = username;
        container[username].push(client);
    });

    client.on('set account offline', function(username) {
        if (username in container) {
            delete container[username];
            console.log(username + " is now Offline" );
        }
    });
然后,当发送消息时,我遍历相应的数组元素

   client.on('send message', function(data) {
        if (data.recipient in container) {
            var clients = container[data.recipient];
            for(var i = 0; i < clients.length;i++){
                clients[i].emit('send message', {recipient: data.recipient, message: data.message });
            }
        }
    });
client.on('send message',函数(数据){
if(容器中的data.recipient){
var clients=container[data.recipient];
对于(var i=0;i
这一切都很好(但不确定它的编码有多好)。问题是,如果用户关闭一个选项卡,那么该选项卡的套接字仍然存在于
容器
变量中,并且如果接收到该特定用户的消息,节点仍将尝试向该套接字发出消息。此外,它只是觉得更清洁,以取消跟踪任何断开的插座

我一直在考虑这一点,我认为我必须将套接字断开连接事件与客户端的
onbeforeuload
事件联系起来,我们都知道这在不同浏览器中是如何执行的。关于从
容器
阵列拼接断开的插座的正确方法,有什么建议吗?

根据我的评论:


你真的应该去执行房间。在每个连接上,每个用户 应该加入自己的房间,任何额外的连接都来自同一个房间 用户应该加入这个房间。然后,您可以将数据发射到房间并 其中的每个客户端都将接收数据

您的代码可以更改为:

io.sockets.on('connection', function(client) {

    client.on('set account online', function(username) {
        client.join(username);
    });

    client.on('set account offline', function(username) {
        client.leave(username);
    });

    client.on('send message', function(data) {
        io.to(data.recipient).emit('send message', {
            recipient: data.recipient,
            message: data.message
        });
    });
});
根据我的评论:


你真的应该去执行房间。在每个连接上,每个用户 应该加入自己的房间,任何额外的连接都来自同一个房间 用户应该加入这个房间。然后,您可以将数据发射到房间并 其中的每个客户端都将接收数据

您的代码可以更改为:

io.sockets.on('connection', function(client) {

    client.on('set account online', function(username) {
        client.join(username);
    });

    client.on('set account offline', function(username) {
        client.leave(username);
    });

    client.on('send message', function(data) {
        io.to(data.recipient).emit('send message', {
            recipient: data.recipient,
            message: data.message
        });
    });
});
根据我的评论:


你真的应该去执行房间。在每个连接上,每个用户 应该加入自己的房间,任何额外的连接都来自同一个房间 用户应该加入这个房间。然后,您可以将数据发射到房间并 其中的每个客户端都将接收数据

您的代码可以更改为:

io.sockets.on('connection', function(client) {

    client.on('set account online', function(username) {
        client.join(username);
    });

    client.on('set account offline', function(username) {
        client.leave(username);
    });

    client.on('send message', function(data) {
        io.to(data.recipient).emit('send message', {
            recipient: data.recipient,
            message: data.message
        });
    });
});
根据我的评论:


你真的应该去执行房间。在每个连接上,每个用户 应该加入自己的房间,任何额外的连接都来自同一个房间 用户应该加入这个房间。然后,您可以将数据发射到房间并 其中的每个客户端都将接收数据

您的代码可以更改为:

io.sockets.on('connection', function(client) {

    client.on('set account online', function(username) {
        client.join(username);
    });

    client.on('set account offline', function(username) {
        client.leave(username);
    });

    client.on('send message', function(data) {
        io.to(data.recipient).emit('send message', {
            recipient: data.recipient,
            message: data.message
        });
    });
});

你真的应该实施。在每个连接上,每个用户都应该加入他们自己的房间,来自同一用户的任何其他连接都应该加入这个房间。然后,您可以将数据发送到房间,房间内的每个客户机都将接收数据。这就是为什么:“在断开连接时,套接字会自动离开它们所属的所有通道,而您不需要特别拆卸。”?您应该真正实现。在每个连接上,每个用户都应该加入他们自己的房间,来自同一用户的任何其他连接都应该加入这个房间。然后,您可以将数据发送到房间,房间内的每个客户机都将接收数据。这就是为什么:“在断开连接时,套接字会自动离开它们所属的所有通道,而您不需要特别拆卸。”?您应该真正实现。在每个连接上,每个用户都应该加入他们自己的房间,来自同一用户的任何其他连接都应该加入这个房间。然后,您可以将数据发送到房间,房间内的每个客户机都将接收数据。这就是为什么:“在断开连接时,套接字会自动离开它们所属的所有通道,而您不需要特别拆卸。”?您应该真正实现。在每个连接上,每个用户都应该加入他们自己的房间,来自同一用户的任何其他连接都应该加入这个房间。然后,您可以将数据发送到房间,房间内的每个客户机都将接收数据。这就是为什么:“断开连接后,插座会自动离开它们所属的所有通道,您不需要特别拆卸。”?是的,谢谢。这项工作做得很好。但是,我在从客户端发送用户名时遇到了一个问题。从技术上讲,由于客户端中的任何内容都可以被某个恶意用户修改,因此任何人都可以更改用户名并有效地为另一个用户触发事件。节点是否应该访问数据库和某种会话实现?我在我的PHP应用程序中运行这个,节点提供聊天功能。我已经设法使用jsonwebtokens进行身份验证。谢谢你的帮助。对不起,刚刚看到这个。会话存储是整合两者的好方法,Redis通常是最受欢迎的。@BenFortune是对的——以我的经验,从长远来看,会话是最简单的解决方案。无论您是使用json web令牌还是使用cookie作为秘密,这都无关紧要,会话存储都与此相关。下面是我如何基于Sails core中的套接字id实现访问Connect会话存储的:是的,谢谢。这项工作做得很好。但是,我在从客户端发送用户名时遇到了一个问题。从技术上讲,由于客户端中的任何内容都可以被某个恶意用户修改,因此任何人都可以更改用户名并有效地为另一个用户触发事件。节点是否应该访问数据库和某种会话实现?我正在用node providin运行我的PHP应用程序