登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  前端

WebSocket close 事件 code 为 1006 时浏览器能提供什么线索

来源:17golang原创

时间:2026-09-08 21:27:41 286浏览 收藏

如果浏览器的 WebSocket close 事件得到 event.code === 1006,先记住一个关键结论:1006 不是服务端在 Close 帧里发送的普通状态码,而是浏览器用来表示连接没有完成可观测的正常关闭。它能说明连接异常结束,却不能单独告诉你是 DNS、TLS、代理、服务端进程还是网络路径出了问题。

1006 的价值是触发“分层取证”,不是直接给出根因。优先保存 codereasonwasCleanreadyStateerror 事件和时间戳,再与 Network 及服务端日志对照。
要点速览
  • code=1006 表示浏览器没有拿到可传递的正常关闭码,不能当成服务端业务错误码。
  • reason 为空并不意外;它只有在收到关闭原因且浏览器允许暴露时才有诊断价值。
  • 重连前先区分握手失败、连接中途断开和服务端主动关闭,避免把故障放大成重连风暴。

先看懂 1006:它不是服务端发来的普通关闭码

WebSocket 的关闭码来自关闭握手。RFC 6455 将 1006 列为保留值,不能作为实际 Close 帧中的状态码发送;WHATWG 规范则规定,在连接失败、TLS 握手失败、开握手未完成,或服务器在握手后突然断开等多种情形下,浏览器脚本可观察到 1006。这样做也避免页面脚本借助细微错误差异探测用户网络。

所以,1006 的“线索”主要来自相邻字段:

字段能说明什么不能说明什么
code浏览器最终呈现的关闭码不能定位具体网络组件
reason服务端提供的关闭原因(可能为空)为空不等于没有故障
wasClean是否完成干净关闭不能代替服务端日志
readyState连接最终进入 CLOSED 等状态不能还原丢失的 Close 帧
浏览器观测边界、CloseEvent 字段与网络外部原因的静态关系图
图1:把浏览器能看到的 CloseEvent 字段与网络外部原因分开,理解 1006 为什么只能作为异常关闭线索。

用一段 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、Network、服务端、代理和 TLS 记录的静态证据关系图
图2:1006 本身不能定位根因,需将客户端字段与 Network、服务端、代理和 TLS 记录放在同一证据链中对照。

重连、兼容与上线时的三个边界

  • 重连:使用指数退避并设置上限;认证失败、协议不匹配等确定性错误不应无限重连。
  • 兼容:CloseEventclose 事件在现代浏览器中已广泛可用,但仍应保留服务端日志作为跨端事实来源。
  • 安全:不把 reason 原样展示给用户,也不记录 Cookie、Token 或完整消息内容;日志只留必要的端点、时间、状态和关联 ID。

实际排查时,可以把结论写成“1006 + 是否 open + wasClean + 存在的帧 + 服务端是否见到连接”五元组。这样既不会把 1006 误当成根因,也能让前端、网关和后端围绕同一条连接快速对齐。

常见问题

服务端可以主动发送 1006 吗?

不应这样做。1006 是保留状态值,服务端应选择协议允许的实际关闭码并提供合适的 reason;浏览器最终显示 1006,通常意味着没有可供脚本读取的正常关闭帧。

为什么 1006 时 reason 经常是空字符串?

因为浏览器可能没有收到 Close 帧,或者关闭原因没有随协议完成传递。空 reason 只说明客户端没有可用原因文本,不能据此断言服务端没有记录。

参考资料

MDN CloseEventMDN WebSocket close eventWHATWG WebSockets StandardRFC 6455 状态码

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>