【问题标题】:Maintain socketio conection to each new tab opened by the same user保持与同一用户打开的每个新选项卡的套接字 io 连接
【发布时间】:2015-01-30 10:58:47
【问题描述】:

我正在为我们的网站制作一个应用程序,用户可以在其中互相发送聊天消息。我已经成功地使用 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 });
            }
        }
    });

这一切都很好(虽然不确定它的编码有多好)。问题是如果用户关闭一个选项卡,该选项卡的套接字仍然存在于container 变量中,并且如果收到该特定用户的消息,节点仍会尝试向该套接字发出。此外,取消跟踪任何断开连接的套接字感觉更干净。

我一直在考虑这个问题,我认为我必须将套接字断开连接事件与客户端的 onbeforeunload 事件联系起来,我们都知道它在不同浏览器中的执行方式。关于从container 数组拼接断开的套接字的正确方法是什么?

【问题讨论】:

  • 你真的应该实现rooms。在每个连接上,每个用户都应该加入他们自己的房间,来自同一用户的任何其他连接都应该加入这个房间。然后,您可以向房间发送数据,房间内的每个客户端都将接收数据。
  • 有趣。这就是为什么:“断开连接后,套接字会自动离开它们所属的所有通道,并且您不需要特别拆除。” ?

标签: node.js websocket socket.io


【解决方案1】:

根据我的评论:

您真的应该实施房间。在每个连接上,每个用户 应该加入他们自己的房间,来自同一房间的任何其他连接 用户应该加入这个房间。然后您可以将数据发送到房间并 里面的每个客户端都会收到数据。

您的代码可以更改为:

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 核心中的套接字 id 访问 Connect 会话存储:github.com/balderdashy/sails-hook-sockets/blob/master/lib/…
猜你喜欢
  • 2020-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 2019-04-14
相关资源
最近更新 更多