websocket连接失败需分段排查:先查network中是否返回101响应及upgrade头,再验send前readystate是否为open,接着确认消息类型匹配与url编码,最后通过1006码和心跳机制诊断频繁断连。

WebSocket 报错不能只盯着控制台那句“connection failed”或“InvalidStateError”,真正的问题往往藏在连接生命周期、网络层响应和状态流转里。快速排查的关键是分段验证:先看握手成没成,再看发没发出去,最后看收不收得到。
一、连接建立失败:先查 Network 面板里的 101 响应
浏览器控制台报 WebSocket connection failed 或直接显示 failed,90% 是握手卡在 HTTP 升级阶段。打开 Network → Filter 输入 ws,点开连接项:
- 状态码不是 101 Switching Protocols?说明服务端或代理(如 Nginx)没完成协议升级;
- 响应头里缺
Upgrade: websocket或Connection: Upgrade?Nginx 必须配全这三行:proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade"; - 根本没出现在 Network 列表里?检查 URL 协议是否写错(
http://写成ws://)、端口是否匹配、域名是否同源(https://a.com页面不能连wss://b.com); - 用 curl 验证后端是否可达:
curl -i -N -H "Connection: upgrade" -H "Upgrade: websocket" https://yourdomain.com/ws,看到 101 才算通。
二、发送时报 InvalidStateError:readyState 不是 OPEN
调用 ws.send() 突然抛错,核心原因永远只有一个:此时 ws.readyState !== WebSocket.OPEN(即不是 1)。常见于:
- Vue
onMounted或 ReactuseEffect里立即发消息,但onopen还没触发,readyState仍是CONNECTING (0); - 重连逻辑中旧连接已关闭,新连接还没 ready,就调了 send;
- 全局单例 WebSocket 被提前导出,使用者没等 open 就调用。
安全做法是封装发送函数:
- 简单版:每次 send 前加判断
if (ws.readyState === WebSocket.OPEN) { ws.send(...) }; - 可靠版:用 Promise 等待 open 事件:
function waitForOpen(ws) { return new Promise(r => ws.readyState === 1 ? r() : ws.addEventListener('open', r, { once: true })) }; - 别用轮询(比如每 5ms 查一次),既卡主线程又不可靠。
三、连上了却没反应:消息路径上某处丢了
Network 里能看到连接、onopen 触发了、send 也调了,但服务端没日志,或前端 onmessage 死活不进——问题不在连接,而在消息流转环节:
- 发的是 ArrayBuffer/Blob,但后端 @OnMessage 只写了 String 参数(Java)或没监听 binary(Node.ws),帧类型不匹配就会静默丢弃;
- Chrome DevTools 的 WS → Frames 标签页里,确认发送帧的 Type 是 Text(不是 Binary),且内容是合法 JSON 字符串;
- URL 里带 token 参数但含特殊字符(如
+、空格、/),没做encodeURIComponent,后端解析失败直接拒绝; - 反向代理(如 Nginx)设置了
proxy_read_timeout 60,空闲 60 秒后主动断连,前端仍以为 OPEN,后续 send 实际失效;需加大并配proxy_send_timeout。
四、频繁断连:重点盯 1006 和心跳机制
连接建立几秒后自动关闭,onclose 中 event.code === 1006 是最常见信号,代表“异常关闭”,不是业务主动关的:
- 不是代码 bug,而是网络中断、服务端崩溃、或中间代理(防火墙/NAT/云 WAF)超时切断;
- 必须加心跳:每 25–30 秒发一次
"ping",服务端回"pong";连续 2–3 次无响应,就主动ws.close()并重连; - 别依赖
onerror——它不带错误详情,只算兜底提示;真正诊断要靠onclose.code、Network 面板、服务端日志三者交叉比对; - 重连时先检查
ws.readyState:是CLOSED (3)才新建,是CONNECTING (0)就等等,避免并发连接。
不复杂但容易忽略:WebSocket 故障从来不是单一环节的问题,而是握手、传输、保活、错误处理四个环节环环相扣。把 Network 面板当第一现场,把 readyState 当状态标尺,把心跳当生命线,基本就能稳住大部分实时通信场景。











