【问题标题】:Node.js Socket.io sets up multiple connectionsNode.js Socket.io 设置多个连接
【发布时间】:2018-02-21 10:53:17
【问题描述】:

我正在创建一个使用 passport.js 进行身份验证的简单 socket.io 聊天。但是每次用户注销并登录时,旧的套接字连接都会重新连接。这会导致问题,因为现在有两个活动连接到一个页面。所以我想要做的是当用户导航到“/logout”时结束当前连接。

var socketNotLoaded = true;
var socket;

app.get('/', function(req, res) {
    if (req.isAuthenticated()) {
        if(socketNotLoaded) { //is true when new connection is required
            require("./socket")(io,req.user) //runs the socket.io script
            socketNotLoaded = false;
        }
        res.render('index', pug.get(req.user));
    } else {
        res.render('notloggedin', pug.get());
    }
})

app.get('/logout', function(req, res) {
    socketNotLoaded = true;
    req.logout();
    res.redirect('/');
})

我正在使用

  • socket.io: 2.0.3
  • 护照:0.4.0
  • 护照本地:1.0.0
  • 快递:4.15.4
  • 快速会话:1.15.5
  • cookie 解析器:1.4.3
  • 正文解析器:1.17.2

【问题讨论】:

  • 显然您的网页中有客户端代码在您注销并重新连接后重新连接。这很可能是问题所在。另外,您的代码似乎只为一位用户设计。如果if(socketNoLoaded) 调用使用模块级变量来决定是否使用req.user 初始化socket.io。那是没有意义的。当第二个用户访问您的网站时,您期望会发生什么?还是第三个用户?
  • 哦,我明白了。我应该如何解决这个问题?
  • 老实说,我不明白你在做什么。在我看来,您当前的设计存在根本缺陷。每个用户的状态需要在您的会话中,而不是在模块级变量中。 socket.io 服务器应该在服务器启动时初始化,同时你的 web 服务器也被初始化。它应该始终在运行,并且不应使用任何每个用户的状态进行初始化。您不会为每个用户创建一个新的 socket.io 服务器,您有一个所有用户都使用的 socket.io 服务器(就像您的 Web 服务器一样)。
  • 谢谢,现在更有意义了。但是我如何安全地向 socket.io 提供活跃用户的详细信息?
  • 我不知道“提供活跃用户详细信息”是什么意思?什么是“活跃用户详细信息”,为什么要将它们提供给 socket.io 服务器?

标签: javascript node.js express socket.io passport.js


【解决方案1】:

在客户端,当用户想要注销时,您可以执行socket.emit('exit');,然后在服务器端有一个监听器,如下所示:

socket.on('exit', function(){
    socket.disconnect();
});

这将断开客户端与 Socket.io 的连接。您还可以在服务器端创建一个将用户名映射到 Socket.io 套接字 ID 的对象,并执行检查以查看该用户是否已经存在。如果是这样,那么您可以在服务器端断开该套接字 ID。理想情况下,客户端应在用户注销时向服务器发送disconnect。像这样的:

 $('#logout').click( function() {
            socket.disconnect();
            window.location = "/logout";
});

【讨论】:

  • 我已经尝试过了,但是您第二次登录时仍然有两个实时连接。
  • 客户端可以随时断开连接。它不需要向服务器发送消息来告诉服务器断开连接。另外,OP 的代码在注销后重定向,因此当前的套接字连接无论如何都会在重定向时被终止。
  • 正如@jfriend00 所说,您可以让客户端断开连接。我们不知道您是如何做到这一点的,因为您没有提供您的客户端代码。
  • 在客户端发生的所有事情都是用户被重定向到“/logout”并进行初始连接。 var socket = io.connect(window.location.href.split("/")[2]);
  • 好吧,假设注销类似于单击按钮,为该按钮创建一个事件侦听器,然后调用socket.disconnect(),然后执行重定向window.location = "/logout";
猜你喜欢
  • 2017-06-14
  • 2018-05-14
  • 1970-01-01
  • 2016-03-20
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
  • 1970-01-01
相关资源
最近更新 更多