WebSocket close 事件 code 为 1006 时浏览器能提供什么线索
来源:17golang原创
时间:2026-09-08 21:27:41 286浏览 收藏
如果浏览器的 WebSocket close 事件得到 event.code === 1006,先记住一个关键结论:1006 不是服务端在 Close 帧里发送的普通状态码,而是浏览器用来表示连接没有完成可观测的正常关闭。它能说明连接异常结束,却不能单独告诉你是 DNS、TLS、代理、服务端进程还是网络路径出了问题。
1006 的价值是触发“分层取证”,不是直接给出根因。优先保存code、reason、wasClean、readyState、error事件和时间戳,再与 Network 及服务端日志对照。
code=1006表示浏览器没有拿到可传递的正常关闭码,不能当成服务端业务错误码。reason为空并不意外;它只有在收到关闭原因且浏览器允许暴露时才有诊断价值。- 重连前先区分握手失败、连接中途断开和服务端主动关闭,避免把故障放大成重连风暴。
先看懂 1006:它不是服务端发来的普通关闭码
WebSocket 的关闭码来自关闭握手。RFC 6455 将 1006 列为保留值,不能作为实际 Close 帧中的状态码发送;WHATWG 规范则规定,在连接失败、TLS 握手失败、开握手未完成,或服务器在握手后突然断开等多种情形下,浏览器脚本可观察到 1006。这样做也避免页面脚本借助细微错误差异探测用户网络。
所以,1006 的“线索”主要来自相邻字段:
| 字段 | 能说明什么 | 不能说明什么 |
|---|---|---|
code | 浏览器最终呈现的关闭码 | 不能定位具体网络组件 |
reason | 服务端提供的关闭原因(可能为空) | 为空不等于没有故障 |
wasClean | 是否完成干净关闭 | 不能代替服务端日志 |
readyState | 连接最终进入 CLOSED 等状态 | 不能还原丢失的 Close 帧 |

用一段 close 监听代码留下最小诊断样本
不要只打印一句“WebSocket disconnected”。下面的监听器把一次连接的关键上下文保存下来;error 事件通常不给出可依赖的细节,因此要把它当作异常信号,而不是根因字符串。
function watchSocket(socket, endpoint) {
const openedAt = Date.now();
socket.addEventListener("error", () => {
// error 事件只表示连接出现异常,不把浏览器内部原因当成事实。
console.warn("WebSocket error", { endpoint, at: Date.now() });
});
socket.addEventListener("close", (event) => {
// 1006 是异常关闭线索,不是可由服务端发送的业务码。
const sample = {
endpoint,
code: event.code,
reason: event.reason,
wasClean: event.wasClean,
readyState: socket.readyState,
lifetimeMs: Date.now() - openedAt
};
// 只记录必要字段,避免把令牌或用户数据写入日志。
console.info("WebSocket close sample", sample);
});
}
把 endpoint 做脱敏,例如只保留主机和路径模板,不要把查询参数中的令牌写入日志。lifetimeMs 还能帮助区分“刚创建就失败”和“运行一段时间后被断开”,但它仍然只是相关性线索。
把 1006 变成可排查的证据链
第一层看连接是否真的完成过 open:若没有,重点检查 URL、Origin、协议协商、证书和代理升级配置;若已经 OPEN 后才出现 1006,则继续对照服务端是否重启、进程是否被回收、负载均衡是否有空闲超时,以及网络是否发生切换。浏览器 Network 面板能看到握手和已记录的 WebSocket 帧,但看不到所有底层失败细节。
第二层按同一个请求 ID 或连接 ID 对齐服务端连接日志、反向代理记录和 TLS/网络观测。若服务端记录了明确的关闭码与原因,优先以服务端协议日志解释;若服务端完全没有收到连接,则把排查范围前移到 DNS、TLS、代理和网络路径。客户端的 1006 不足以在这些情况之间做唯一判断。

重连、兼容与上线时的三个边界
- 重连:使用指数退避并设置上限;认证失败、协议不匹配等确定性错误不应无限重连。
- 兼容:
CloseEvent和close事件在现代浏览器中已广泛可用,但仍应保留服务端日志作为跨端事实来源。 - 安全:不把
reason原样展示给用户,也不记录 Cookie、Token 或完整消息内容;日志只留必要的端点、时间、状态和关联 ID。
实际排查时,可以把结论写成“1006 + 是否 open + wasClean + 存在的帧 + 服务端是否见到连接”五元组。这样既不会把 1006 误当成根因,也能让前端、网关和后端围绕同一条连接快速对齐。
常见问题
服务端可以主动发送 1006 吗?
不应这样做。1006 是保留状态值,服务端应选择协议允许的实际关闭码并提供合适的 reason;浏览器最终显示 1006,通常意味着没有可供脚本读取的正常关闭帧。
为什么 1006 时 reason 经常是空字符串?
因为浏览器可能没有收到 Close 帧,或者关闭原因没有随协议完成传递。空 reason 只说明客户端没有可用原因文本,不能据此断言服务端没有记录。
参考资料
MDN CloseEvent、MDN WebSocket close event、WHATWG WebSockets Standard、RFC 6455 状态码。
-
311 收藏
-
447 收藏
-
493 收藏
-
156 收藏
-
370 收藏
-
文章 · 前端 | 1小时前 | javascript · Fetch API · 前端请求 · 异步取消 · AbortController AbortSignal.any AbortSignal.timeout fetch取消请求263 收藏
-
238 收藏
-
168 收藏
-
文章 · 前端 | 6小时前 | javascript · structuredClone · 对象复制 · JavaScript 深拷贝 structuredClone DataCloneError377 收藏
-
349 收藏
-
199 收藏
-
文章 · 前端 | 11小时前 | 前端 · 性能 · javascript · 浏览器API · Web Worker · ArrayBuffer postMessage Web Worker structured clone transfer list290 收藏
-
418 收藏
-
文章 · 前端 | 13小时前 | 前端 · pwa · Service Worker · 缓存更新 · Service Worker skipWaiting clientsClaim 缓存版本 前端缓存更新410 收藏
-
422 收藏
-
432 收藏
-
398 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习