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

Discord WebSocket运行数小时后停止接收消息,重启Node可恢复

问题:Discord WebSocket连接1-2小时后停止接收消息

已实现Discord WebSocket用于接收即时消息,初始运行一切正常,但在1-2小时内的某段时间后,日志文件停止记录消息。重启Node进程后,消息记录功能恢复正常,目前无法确定问题原因。

原代码

const WebSocket = require('ws');

const ws = new WebSocket("wss://gateway.discord.gg/?v=6&encoding=json");
let interval = 0;

token = 'SOME tOKEN';
payload = {
    op:2,
    d:{
       token:token,
       properties:{
           $os:'linux',
           $browser:'chrome',
           $device:'chrome'
       }
   }
}

ws.on('open', function open(){
    ws.send(JSON.stringify(payload))
})

ws.on('message', function incoming(data){
    let payload = JSON.parse(data)
    const {t, event, op, d} = payload;

    switch (op){
        case 10:
            const {heartbeat_interval} = d;
            interval = heartbeat(heartbeat_interval)
            break;
    }
    switch (t){
        case 'MESSAGE_CREATE':
             let author = d.author.username;
             let content = d.content;

             console.log(d);
                
    }
})

const heartbeat = (ms) => {
    return setInterval(() => {
         ws.send(JSON.stringify({op:1,d:null}))
    },ms)
}

问题原因及修复方案

核心问题点

  1. 无连接异常处理:原代码未监听error和close事件,无法感知连接断开或异常,自然无法触发重连
  2. 心跳机制不完善:仅启动心跳但未处理Discord的心跳确认(op:11),也未检查连接状态,心跳可能在连接断开后无效发送
  3. 全局变量污染:token和payload未用let/const声明,属于全局变量,可能引发意外问题

修复后的代码

const WebSocket = require('ws');

const token = 'YOUR_TOKEN_HERE';
let ws;
let heartbeatInterval;

// 初始化连接函数,用于首次连接和重连
function connect() {
    ws = new WebSocket("wss://gateway.discord.gg/?v=6&encoding=json");

    const payload = {
        op: 2,
        d: {
            token: token,
            properties: {
                $os: 'linux',
                $browser: 'chrome',
                $device: 'chrome'
            }
        }
    };

    ws.on('open', () => {
        ws.send(JSON.stringify(payload));
        console.log('WebSocket连接已建立');
    });

    ws.on('message', (data) => {
        const payload = JSON.parse(data);
        const { t, op, d } = payload;

        switch (op) {
            case 10:
                const { heartbeat_interval } = d;
                startHeartbeat(heartbeat_interval);
                break;
            case 11:
                // 收到Discord的心跳确认,可用于排查心跳是否正常
                console.log('心跳确认收到');
                break;
        }

        if (t === 'MESSAGE_CREATE') {
            console.log(`[${d.author.username}]: ${d.content}`);
        }
    });

    // 监听连接错误
    ws.on('error', (err) => {
        console.error('WebSocket错误:', err);
        reconnect();
    });

    // 监听连接关闭
    ws.on('close', (code, reason) => {
        console.log(`WebSocket连接关闭,代码: ${code},原因: ${reason.toString()}`);
        stopHeartbeat();
        reconnect();
    });
}

// 启动心跳
function startHeartbeat(ms) {
    stopHeartbeat();
    heartbeatInterval = setInterval(() => {
        // 仅在连接处于OPEN状态时发送心跳
        if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({ op: 1, d: null }));
            console.log('发送心跳');
        } else {
            console.log('WebSocket未连接,跳过心跳');
        }
    }, ms);
}

// 停止心跳
function stopHeartbeat() {
    if (heartbeatInterval) {
        clearInterval(heartbeatInterval);
        heartbeatInterval = null;
    }
}

// 触发重连
function reconnect() {
    console.log('5秒后尝试重连...');
    setTimeout(connect, 5000);
}

// 启动初始连接
connect();

修复说明

  • 新增connect()函数统一管理连接逻辑,支持重连调用
  • 添加error和close事件监听,连接异常时自动触发重连
  • 处理心跳确认op:11,确保心跳机制闭环
  • 心跳发送前检查连接状态,避免无效操作
  • 用let/const声明所有变量,消除全局污染
  • 添加关键节点日志,便于排查连接状态变化

内容的提问来源于stack exchange,提问作者Rahul Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:27:21