You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebSocket多客户端场景下断连检测失效问题如何修复?

问题原因与修复方案

你的代码核心问题是所有客户端共享了全局的定时器变量tm,导致多个客户端连接时定时器互相覆盖,功能异常。具体错误点如下:

  • 全局变量tm存储定时器引用:第二个客户端连接执行ping()时,会直接覆盖第一个客户端绑定的定时器ID,导致第一个客户端的超时逻辑丢失,超时后只会触发最新客户端的断连判定
  • 定时器清除API用错:pong()里使用clearInterval()清除setTimeout()创建的定时器,API不匹配,根本无法正常清除超时计时
  • 消息处理分支逻辑错误:非__ping__的消息分支中,既没有赋值msg变量,也没有执行日志输出语句,还直接把未定义的msg发送给客户端,会触发运行时报错

修复后的完整代码

const WebSocket = require("ws");
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const url = require('url');

const PORT = process.env.PORT || 3000;

const wss = new WebSocket.Server({ server: server });
app.get("/", (req, res) => res.send("Test."));

// 给每个连接的客户端单独绑定定时器,不再使用全局变量
function ping(ws, clientId) {
  // 把定时器挂载到当前ws实例上,每个客户端独立存储
  ws.tm = setTimeout(function () {
    console.log(`[-] ${clientId} Disconnected`);
    wss.emit("customClose", clientId);
    // 触发断连后主动关闭对应客户端的连接
    ws.terminate();
  }, 5000);
}

function pong(ws, clientId) {
  // 用clearTimeout清除定时器
  clearTimeout(ws.tm);
  ping(ws, clientId);
}

wss.on("connection", function connection(ws, req) {
  var queryData = url.parse(req.url,true).query;
  const clientId = queryData.id;
  // 给当前连接的客户端初始化专属定时器
  ping(ws, clientId);
  console.log(`[+] ${req.socket.remoteAddress} Connected`);

  wss.clients.forEach(function each(client) {
    if (client.readyState === WebSocket.OPEN) {
      const message = {
        type: "alert",
        msg: `${clientId} has Connected.`,
      };
      client.send(JSON.stringify(message), { binary: false });
    }
  });

  ws.on("message", function incoming(message) {
    if (message == "__ping__") {
      console.log(`[!] Ping Received from ${req.socket.remoteAddress}`);
      pong(ws, clientId);
    } else {
      console.log(`[!] Message Received from ${req.socket.remoteAddress}: ${message}`);
     
      wss.clients.forEach(function each(client) {
        if (client.readyState === WebSocket.OPEN) {
          const msg = JSON.stringify({
            type: "message",
            content: message.toString()
          });
          client.send(msg, { binary: false });
        }
      });
    }
  });

  // 新增客户端主动断连的处理逻辑,清除定时器
  ws.on("close", () => {
    clearTimeout(ws.tm);
    console.log(`[*] Client ${clientId} actively disconnected`);
  });
});

wss.addListener("customClose", function (m) {
  wss.clients.forEach(function each(client) {
    if (client.readyState === WebSocket.OPEN) {
      const message = {
        type: "alert",
        msg: `${m} has Disconnected.`,
      };
      client.send(JSON.stringify(message), { binary: false });
    }
  });
});

server.listen(PORT, () => console.log(`Listening on port ${PORT}`));

修复说明

  1. 移除了全局tm变量,改为将每个客户端的定时器挂载到对应ws连接实例上,实现连接级别的隔离,多个客户端的定时器不会互相干扰
  2. 把clearInterval替换为clearTimeout,匹配定时器创建的API
  3. 修复了非ping消息分支的逻辑错误,补全了日志输出、消息封装逻辑,避免未定义变量报错
  4. 新增了客户端主动断连的close事件监听,及时清理残留定时器,避免内存泄漏
  5. 修正了代码中拼写错误的Receieved为Received,测试页内容Temst为Test

内容的提问来源于stack exchange,提问作者Ballistic Swami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:06:00