WebSocket close 事件 code 为 1006 时浏览器能提供什么线索
如果浏览器的 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 状态码。
Go JSON Unmarshal 复用结构体时旧指针字段为什么残留
- 上一篇
- Go JSON Unmarshal 复用结构体时旧指针字段为什么残留
- 下一篇
- Go testing.T Setenv 怎么避免并行测试互相污染
-
- 文章 · 前端 | 1小时前 | javascript · Fetch API · 前端请求 · 异步取消 · AbortController AbortSignal.any AbortSignal.timeout fetch取消请求
- JavaScript AbortSignal.timeout 和手动 AbortController 怎么选
- 263浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- CSS subgrid 为什么能让嵌套卡片对齐同一列轨道
- 238浏览 收藏
-
- 文章 · 前端 | 4小时前 |
- Fetch 上传 ReadableStream 时怎么设置 duplex: half
- 168浏览 收藏
-
- 文章 · 前端 | 6小时前 | javascript · structuredClone · 对象复制 · JavaScript 深拷贝 structuredClone DataCloneError
- JavaScript structuredClone 复制对象时哪些值仍然不能克隆
- 377浏览 收藏
-
- 文章 · 前端 | 7小时前 | 布局 · 前端 · css · 响应式布局 卡片组件 CSS container queries
- CSS container query 怎么让卡片按父容器宽度切换布局
- 349浏览 收藏
-
- 文章 · 前端 | 9小时前 |
- 前端 Worker terminate 后未完成消息怎么处理
- 199浏览 收藏
-
- 文章 · 前端 | 11小时前 | 前端 · 性能 · javascript · 浏览器API · Web Worker · ArrayBuffer postMessage Web Worker structured clone transfer list
- 前端 Web Worker 传输对象后为什么主线程拿到的是副本
- 290浏览 收藏
-
- 文章 · 前端 | 12小时前 |
- 前端 Service Worker fetch 拦截如何绕过不该缓存的请求
- 418浏览 收藏
-
- 文章 · 前端 | 13小时前 | 前端 · pwa · Service Worker · 缓存更新 · Service Worker skipWaiting clientsClaim 缓存版本 前端缓存更新
- 前端 Service Worker 的 skipWaiting 和 clientsClaim 怎么安排版本切换
- 410浏览 收藏
-
- 文章 · 前端 | 15小时前 |
- 前端 createObjectURL 预览文件后什么时候 revoke
- 422浏览 收藏
-
- 文章 · 前端 | 16小时前 |
- 前端 Blob.slice 上传分片时怎么计算最后一片长度
- 432浏览 收藏
-
- 文章 · 前端 | 17小时前 |
- 前端 IndexedDB 事务自动提交前为什么不能异步等待
- 398浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 30次使用
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 187次使用
-
- C-Eval
- 深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
- 120次使用
-
- AI Prompt Library
- 探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
- 46次使用
-
- Generrated
- Generrated汇集9300+张DALL·E生成图像及对应提示词,支持查看完整图集、对比DALL·E 2与3版本差异,是AI绘图新手学习Prompt设计与获取创作灵感的实用工具。
- 28次使用
-
- golang基于websocket通信tcpkeepalive研究记录
- 2022-12-23 311浏览
-
- golang实现一个简单的websocket聊天室功能
- 2022-12-28 447浏览
-
- Golang使用WebSocket通信的实现
- 2022-12-26 493浏览
-
- 使用Go语言创建WebSocket服务的实现示例
- 2022-12-28 156浏览
-
- golang websocket 服务端的实现
- 2023-02-16 370浏览

