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) }
问题原因及修复方案
核心问题点
- 无连接异常处理:原代码未监听
error和close事件,无法感知连接断开或异常,自然无法触发重连 - 心跳机制不完善:仅启动心跳但未处理Discord的心跳确认(
op:11),也未检查连接状态,心跳可能在连接断开后无效发送 - 全局变量污染:
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
相关产品推荐
相关产品推荐

