Node websockets/ws库:如何区分主动关闭与对方关闭WSS连接?
解决ws库中区分主动/被动关闭连接及Close Code异常问题
我之前在使用ws库处理WSS流的时候,也踩过一模一样的坑——本来想通过传code和reason来区分关闭场景,结果要么没效果要么直接抛异常。结合官方文档和实际调试经验,给你整理几个靠谱的解决办法:
1. 先搞懂ws库关闭连接的正确姿势
你之前的误区可能是把onclose事件当成了可以传参数的方法,但实际上:
- 主动关闭:必须调用实例的
ws.close([code[, reason]])方法来发送关闭指令,这些参数会传递给对方,同时本地的onclose回调也会收到对应的code和reason。 - 被动关闭:
onclose回调里的code和reason是对方发送过来的,或者是连接异常时的系统默认值。
2. 用标记区分主动/被动关闭
最简单直接的方式是在主动关闭前设置一个全局标记,然后在onclose回调里检查这个标记:
const WebSocket = require('ws'); const ws = new WebSocket('wss://your-target-stream'); let isManualClose = false; // 标记是否是主动关闭 // 封装主动关闭函数 function manualClose(code = 1000, reason = 'Normal shutdown') { isManualClose = true; try { ws.close(code, reason); } catch (err) { console.error('主动关闭时出错:', err); } } // 监听关闭事件 ws.on('close', (code, reason) => { if (isManualClose) { console.log(`✅ 主动关闭连接 | Code: ${code}, Reason: ${reason.toString()}`); } else { console.log(`❌ 被动/异常关闭连接 | Code: ${code}, Reason: ${reason.toString()}`); } // 重置标记,避免重连时判断错误 isManualClose = false; }); // 示例:主动关闭(比如用户操作触发) // setTimeout(() => manualClose(4001, '业务逻辑触发关闭'), 5000);
3. 解决Close Code触发异常的问题
ws库对Close Code的校验非常严格,不是随便传个整数就行,必须符合RFC 6455的规范:
- 标准Code(1000-1015):只能用定义好的场景,比如1000是正常关闭,1001是端点离开,不能随便自定义。
- 自定义Code(4000-4999):这部分是留给业务自定义的,比如4001可以代表“业务超时”,4002代表“权限不足”等。
- 其他范围的Code:比如2000-3999、5000+都会直接触发异常,绝对不能用。
另外还要注意:reason字符串的长度不能超过123字节,否则也会抛出错误,所以尽量保持reason简洁。
4. 额外注意事项
- 如果连接已经处于关闭状态,调用
ws.close()会报错,所以最好在调用前先检查ws.readyState是否为WebSocket.OPEN。 - 异常断开(比如网络中断)时,
onclose的code可能是1006(连接异常关闭),这时候reason是空的,需要单独处理。
内容的提问来源于stack exchange,提问作者Birrel
相关产品推荐
相关产品推荐

