WebSocket closed immediately:升级成功却立即断开的原因
WebSocket closed immediately严重程度 High升级握手拿到了 101,连接却在建立后立即被关闭——服务端接纳了协议、拒绝了会话。最可能是服务端校验(路径参数、鉴权信息)失败后主动断开;第一步是运行检测拿到 close code 和 close reason。
结论
这条错误与 upgrade failed 是紧邻的两个阶段:那边是门没开,这边是门开了、进去一秒就被请了出来。101 的达成排除了一大片嫌疑(路径、升级头、中间层的 WebSocket 支持都没问题),剩下的疑点集中在会话层:服务端在升级后的首轮校验里不认可你,或者中间设备放行了握手却掐断了数据。幸运的是,礼貌的关闭会留下 close code——这是本错误最重要的证据。
适用环境
- 全部平台
- 需要鉴权参数的 WebSocket 服务(代理协议、实时接口)尤其高发
一分钟快速判断
connproof websocket wss://你的地址/路径 --hold 5000按报告中的 close code 对号:
| close code | 含义 | 首先检查 |
|---|---|---|
| 1008 | 策略违规 | 鉴权参数(token、user 字段)是否正确完整 |
| 1002 | 协议错误 | 客户端与服务端的子协议/首帧约定 |
| 1011 | 服务端内部错误 | 服务端日志(用户侧只能反馈) |
| 1013 | 稍后再试 | 服务端过载,等待后重试 |
| 无 code(裸断开) | 未走关闭流程 | 中间设备切断,转 WS-003 思路 |
这条错误代表什么
很多 WebSocket 服务把鉴权放在升级之后:先接受连接,再校验 URL 参数或首条消息里的凭据,不合格就发 close 帧走人。这个设计有其道理——在 HTTP 阶段返回 401 会向探测者暴露"这里有一个需要鉴权的 WebSocket 服务",而先升级再沉默关闭让服务的存在感更低。副作用就是排查体验变差:链路层的一切证据(DNS、TCP、TLS、升级)都显示正常,问题藏在应用层的第一轮对话里。这个设计让"链路正常但凭据错误"精确地表现为"升级成功 + 立即关闭"。另一类肇因在链路上:某些检测设备对握手放行(它看起来就是一次 HTTP 请求),而对随后的加密数据流出手——此时断开往往没有 close 帧,表现为裸 FIN 或 RST,与服务端的礼貌关闭可以通过证据区分。
ConnProof 如何判断
检测在升级成功后保持连接并发送一个 ping,记录:升级耗时、连接实际存活的毫秒数、关闭方式(close 帧 + code + reason / FIN / RST)。“立即"的判定阈值是存活时间显著短于保持目标(默认一秒内)。close reason 若服务端提供了文字说明(如 "invalid token"),会原样进入证据——那基本等于服务端把答案写在了纸条上。
最常见原因
- 鉴权参数错误或缺失:URL 里的 token/uuid 抄错、过期、被重置——代理客户端场景的第一大原因;
- 子协议或首帧不符:服务端期待特定的 Sec-WebSocket-Protocol 或首条消息格式;
- 中间设备的数据阶段切断:握手放行、数据被掐,无 close 帧;
- 服务端资源耗尽:接受后立即释放,code 1013 或 1011。
Windows / macOS / Linux 排查步骤
- 检测取 close code;
- code 1008 或 reason 提及鉴权:从服务方面板整体重新复制连接配置(不要手工改 token 的某一段),替换后复测;
- 无 close 帧的裸断开:换网络对比——热点下正常则原链路对 WebSocket 数据流有干扰;
- code 1013/1011:间隔几分钟重试,持续则反馈服务方;
- 多账号可用时交叉验证:换一个有效账号立即成功,锁定原凭据失效。
手机端排查步骤
- 手机客户端通常只报"连接失败",用桌面 ConnProof 取 close code 证据;
- 重新导入配置优先于手工修改;
- Wi-Fi/蜂窝对照区分链路干扰与凭据问题。
如何区分本地问题和节点问题
| 证据 | 更可能是 |
|---|---|
| close 1008 / reason 提及鉴权 | 你的凭据(重新获取配置) |
| close 1011/1013 | 服务端状态(等待/反馈) |
| 无 close 帧、换网络后恢复 | 原链路干扰 |
| 所有用户同时出现 | 服务端发布或故障 |
| 仅单设备失败 | 该设备配置抄写 |
close code 缺席时的推理
不是所有服务端都体贴地附上 close code——你可能拿到一个"礼貌但沉默"的关闭:有 close 帧、无代码无理由。此时还有两条线索可挖。其一是时机的精确度:升级完成到关闭之间隔了多少毫秒?小于 50 毫秒的关闭几乎必然发生在服务端的同步校验里(读取 URL 参数即拒绝);几百毫秒则可能等待过首条消息或查询过外部服务(token 校验走了数据库)。其二是改变量的响应:故意把鉴权参数改错一位再测,如果关闭行为一模一样,说明服务端根本没看参数、拒绝另有原因(比如来源限制);如果原参数被"沉默关闭"而错误参数被"立即断开",恰恰说明原参数已经进入了更深的校验环节。这类对照实验每次只改一个变量,两三轮就能把黑盒摸出轮廓。
仍未解决时收集什么信息
- ConnProof 错误码(WS-002)与脱敏报告;
- close code 与 close reason(关键证据);
- 存活毫秒数、换网络对照结果;
- 客户端名称和版本、操作系统版本。
禁止提交:完整订阅链接、密码、验证码、私钥、Token(close reason 若包含 token 片段,脱敏报告会自动处理)。
重新运行检测
connproof websocket wss://你的地址/路径 --hold 5000 --format markdown --output ws-report.md修复后连接应保持到目标时长并以正常关闭(1000)结束。凭据类修复的验证还有一个额外动作:在所有使用同一配置的设备上各验证一次,避免"改了一台、忘了三台"的返工。
相关文档
更新记录
- 2026-07-28:规则 v1 发布,建立 close code 判读表。