【问题标题】:Socket.IO adding connection when refreshing browser刷新浏览器时Socket.IO添加连接
【发布时间】:2026-02-03 22:55:02
【问题描述】:

我在我的 NodeJS 应用程序上添加了 Socket.IO(顺便说一句,我是新手),当我在 Chrome 上按 F5 刷新网页时,会根据我的服务器日志创建一个新的套接字:

用户已连接 SWpG6Fv9mjmMoLZRAAAA
用户已断开连接 SWpG6Fv9mjmMoLZRAAAA
用户已连接 gvtxcnJR6sC4DW7CAAAB
用户已连接 gvtxcnJR6sC4DW7CAAAB
用户断开连接 gvtxcnJR6sC4DW7CAAAB
用户断开连接 gvtxcnJR6sC4DW7CAAAB
用户连接 pWPjZbVV_-lnVL4RAAAC
用户连接 pWPjZbVV_-lnVL4RAAAC
用户连接 pWPjZbVV_-lnVL4RAAAC
用户断开连接 pWPjZbVV_-lnVL4RAAAC
用户断开连接 pWPjZbVV_-lnVL4RAAAC
用户断开连接 pWPjZbVV_-lnVL4RAAAC
用户已连接 sP7lJaRrH6Hrevp7AAAD
用户已连接 sP7lJaRrH6Hrevp7AAAD
用户已连接 sP7lJaRrH6Hrevp7AAAD
用户已连接 sP7lJaRrH6Hrevp7AAAD
用户已断开连接 sP7lJaRrH6Hrevp7AAAD
用户已断开连接 sP7lJaRrH6Hrevp7AAAD
用户已断开连接 sP7lJaRrH6Hrevp7AAAD
用户已断开连接 sP7lJaRrH6Hrevp7AAAD
用户连接 -86W-itTDwrsyeVGAAAE
用户连接 -86W-itTDwrsyeVGAAAE
用户连接 -86W-itTDwrsyeVGAAAE
用户连接 -86W-itTDwrsyeVGAAAE
用户连接 -86W-itTDwrsyeVGAAAE

关于为什么会发生这种情况的任何想法?

这是我的代码:

index.js:

"use strict";

const express = require('express');
const app = express();
const http = require('http').Server(app);
const socket = require('socket.io')(http);

const opn = require('opn');

const login = require('./scripts/login.js');
const main = require('./scripts/main.js')(socket);
const init = require('./scripts/init.js');
const config = require('./scripts/config.js');

app.use(express.static('public'));
app.set('view engine', 'ejs');
http.listen(3000, function () {
    console.log('==> Servidor iniciado -- Puerto 3000');
});

opn('http://localhost:3000');

app.use('/', main);

ma​​in.js

"use strict";

const express = require('express');
const router = express.Router();
const main = function (socket) {

    // Home page route.
    router.get('/', function (req, res) {
        socket.on('connection', function (socket) {
            console.log('user connected ' + socket.id);
            socket.on('disconnect', function () {
                console.log('user disconnected ' + socket.id);
            });
        });

        res.render('main', {
            page_name: 'main'
        });
    });

    return router;
};

module.exports = main;

index.html

<script src="/socket.io/socket.io.js" charset="utf-8"></script>
<script>
    var socket = io();

    socket.on('connect', function (data) {
        console.log('connected');
    });
</script>

【问题讨论】:

    标签: node.js sockets socket.io


    【解决方案1】:

    您实际上并没有获得多个连接,而是为connection 事件添加了越来越多的侦听器,因此您最终会多次处理同一事件(导致出现多个连接)。

    当您将 socket.io connect 事件侦听器放入这样的路由处理程序中时:

    // Home page route.
    router.get('/', function (req, res) {
        socket.on('connection', function (socket) {
            console.log('user connected ' + socket.id);
            socket.on('disconnect', function () {
                console.log('user disconnected ' + socket.id);
            });
        });
    
        res.render('main', {
            page_name: 'main'
        });
    });
    

    然后,每次/ 路由被命中时,您都会为connection 事件添加另一个重复的侦听器。因此,当一个新的 socket.io 连接发生时,您有多个侦听器,因此您会多次处理同一个连接(创建混乱的日志记录)。

    解决方案通常是将 socket.io 侦听器移到任何路由处理程序之外,以便它们只安装一次。但是,如果由于其他原因将它们放在路由处理程序中,那么您还必须解决其他问题。在任何情况下,socket.io 监听器都必须在任何路由处理程序之外,因此它只在服务器启动时安装一次。

    大概是这样的:

    "use strict";
    const router = require('express').Router();
    
    module.exports = function(io) {
    
        io.on('connection', function (socket) {
            console.log('user connected ' + socket.id);
            socket.on('disconnect', function () {
                console.log('user disconnected ' + socket.id);
            });
        });
    
        // Home page route.
        router.get('/', function (req, res) {
            res.render('main', {
                page_name: 'main'
            });
        });
    
        return router;
    };
    

    注意,您在同一个作用域中还有两个变量都命名为socket。这是一种不好的做法,因为它会阻止对更高范围的访问,并且通常会在处理代码时产生错误或混乱的机会。

    您的更高级别可能应该命名为io,以免与connection 事件的socket 参数混淆,而io 是指主要socket.io 服务器实例时的常用约定。

    【讨论】:

    • 我非常讨厌 JS 回调和监听器...感谢您的帮助
    • @Chico3001 - 好吧,作为一种事件驱动语言,一切都通过 Javascript 中的回调发生,因此您需要学习并熟悉它们,或者可能找到不同类型的编程环境。这确实是 node.js 和浏览器中的 Javascript 工作方式的核心。拥抱它,学习它,与它合而为一,而不是与之抗争。无论如何,很高兴这解决了您的问题。