websocket 意外掉线主要由中间层强制 rst(code 1006)导致,需监听 onclose 判断 event.code === 1006 或 !event.wasclean;连接超时需手动控制;重连须加状态锁、指数退避与次数限制;并配合心跳保活及 visibilitychange 处理。

WebSocket 意外掉线不能靠 onerror 捕获,真正关键的是监听 onclose 并重点识别 event.code === 1006 ——它代表连接被中间层(如 Nginx、LB、iOS 后台回收、防火墙)强制 RST,协议层甚至没机会发关闭帧,占生产环境断连的 70% 以上。
必须监听 onclose 判断 1006 异常断开
浏览器对 1006 是“静默断连”:不触发 onerror,event.reason 为空,wasClean 为 false。只靠 onerror 会漏掉绝大多数真实断连。
- 在
onclose回调中明确检查event.code === 1006或!event.wasClean - 避免仅凭
readyState !== OPEN就判定断连——它可能只是还没连上 - Chrome DevTools → Network → WS → Frames 中若最后是 Ping 但无 Pong,基本可确认服务端或中间件未透传心跳
连接超时要主动控制,不能等默认 20–30 秒
原生 WebSocket 不提供连接超时配置。若服务端启动慢或网络卡顿,客户端会傻等很久才触发 onclose,影响用户体验。
- 创建 socket 后立即设
setTimeout,比如 5 秒内readyState仍不是OPEN,就手动close()并记录“连接超时” -
onopen中清除该定时器,防止误触发 - 超时后应归入统一重连流程,而非直接报错放弃
重连必须带状态锁 + 指数退避 + 次数限制
裸写 onclose → new WebSocket() 容易引发重连风暴,尤其在服务端故障期间,前端会密集发起连接请求,加重服务压力甚至触发限流。
- 用布尔变量(如
isConnecting = false)锁住重连入口,防止多次onclose触发并发连接 - 重连延迟按指数增长:第 1 次等 1s,第 2 次 2s,第 3 次 4s……上限建议 30s
- 设置最大重试次数(如 5 次),超过后停止自动重连,提示用户“连接异常”,并提供手动重试按钮
配合心跳保活,提前发现“假在线”
很多掉线是静默发生的:连接看似还开着(readyState === OPEN),但实际已无法收发数据。仅靠 onclose 被动响应远远不够。
- 客户端每 25–30 秒发一次心跳(如
send({ type: 'ping' })),服务端必须及时回pong - 客户端维护一个定时器,若连续 2 次未收到
pong,主动close()并走重连逻辑 - 移动端需额外监听
visibilitychange:切后台时主动 close,切回前台再重建连接,避免 iOS Safari 30 秒强断
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











