1006错误是客户端在TCP连接异常中断且未收到close帧时自动生成的本地状态码,非服务端发送;常见原因包括Nginx代理超时(默认60秒)、Node.js http.Server默认超时与ws库noServer模式冲突、移动端后台回收及NAT超时等。

1006错误不是服务端发的,是客户端“猜的”
浏览器或客户端 WebSocket 实现(如 Chrome 的 WebSocket 对象)在底层 TCP 连接突然消失、且没收到任何 close 帧时,会本地生成状态码 1006 并触发 onclose。它**不会出现在服务端发送的关闭帧中**(RFC 6455 明确禁止),所以查服务端日志看不到这个码——你看到的只是“连接没了”。
-
event.reason几乎总是空字符串,别依赖它 -
event.wasClean === false是判断 1006 的更可靠依据 -
onerror事件常常不触发,不能只靠它捕获问题
Nginx 代理超时是生产环境最常见原因
哪怕你写了心跳,只要 Nginx 的 proxy_read_timeout 比心跳间隔短,连接就会在第 N 次 ping 后静默断开,客户端收不到任何通知,直接报 1006。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 默认值是
60秒,而很多前端心跳设为 30 秒 —— 第二个 pong 还没回来,Nginx 已经发了 RST - 必须同时设置
proxy_read_timeout和proxy_send_timeout,两者都需 ≥ 心跳间隔 × 2(建议 ≥ 300) - 关键头不能少:
proxy_set_header Upgrade $http_upgrade和proxy_set_header Connection "upgrade"
Node.js ws 库 + 手动 upgrade 时的隐藏陷阱
用 noServer: true 模式并调用 handleUpgrade(),却不监听 server.on('upgrade'),是典型的“自己挖坑自己跳”。Node.js 的 http.Server 仍会对该 socket 施加默认 timeout(60 秒)和 headersTimeout(也常为 60 秒),与 WebSocket 协议无关。
- 错误写法:创建
http.Server后只调handleUpgrade,没绑定upgrade事件 - 正确做法二选一:
– 推荐:new WebSocket.Server({ server })(自动禁用超时)
– 或显式server.on('upgrade', ...)并在回调里调wss.handleUpgrade - HTTPS 场景下,务必传入
https.Server实例,而非裸 socket
移动端和 NAT 环境下的无声掉线
iOS Safari 切后台 30 秒内会强制回收 WebSocket 连接;Android 某些定制 ROM 或运营商 NAT 超时可能低至 90 秒。这类断连没有错误日志、不触发 onclose,直到下次发消息才暴露为 1006。
- 不要等
onclose再重连——要在发消息前检查ws.readyState !== WebSocket.OPEN - 心跳间隔必须 ≤ 最短预期超时(例如设为 45 秒,留出缓冲)
- 客户端主动 close 前,确保先清空定时器、取消未完成请求,否则残留逻辑可能干扰重连状态判断

















