Node.js Socket.io 设置多个连接

Posted

技术标签:

【中文标题】Node.js Socket.io 设置多个连接【英文标题】:Node.js Socket.io sets up multiple connections 【发布时间】: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 服务器? 【参考方案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";

以上是关于Node.js Socket.io 设置多个连接的主要内容,如果未能解决你的问题,请参考以下文章

Socket.io node.js,如何避免记录连接时间或考虑页面刷新/多个套接字?

增加到 node.js/socket.io 的最大连接

在重新连接、socket.io、node.js 时重用套接字 id

socket.io建立长连接

Socket.io 无法在 nginx + node.js + php 应用程序中连接

使用node.js实现多人聊天室(socket.ioB/S)