当前位置:首页 > 文章列表 > 文章 > 前端 > WebSocket 关闭码怎样区分正常断开和异常

WebSocket 关闭码怎样区分正常断开和异常

来源:17golang原创 2026-11-12 12:00:41 0浏览 收藏

页面里的 WebSocket 断开时,控制台往往只留下一句“closed”,真正有用的信息藏在 CloseEvent 里。判断正常还是异常,不能只看一个关闭码:先看 wasClean 表示关闭握手是否完成,再结合 code 的协议含义,最后把 reason 作为服务端或子协议提供的补充线索。

下面只解决一个问题:浏览器收到 close 事件后,怎样把正常离开、服务端主动结束、策略拒绝和连接中断分开处理。

实用判断顺序是:先记录 code、wasClean、reason 三个字段;1000 通常表示正常结束,1001 多数是端点离开,1006 表示没有完成正常关闭握手,其他业务相关码再按 IANA 与 RFC 6455 的含义分流。真正决定是否重连的,不是某个数字本身,而是关闭码和当前页面动作是否一致。

先看 close 事件携带的三个字段

浏览器的 close 事件会交给一个 CloseEvent。其中 code 是连接关闭码,reason 是对端提供的文字原因,wasClean 则表示关闭是否按正常握手完成。三个字段要一起记录,否则只看到“1006”时,很难知道是页面主动离开、服务器重启,还是中间网络突然断开。

WebSocket close 事件把 code、wasClean、reason 汇入应用日志的静态关系说明图
图1:CloseEvent 三个字段与应用日志的静态关系说明图,不是浏览器截图或运行证据。
function attachCloseLog(socket) {
  socket.addEventListener("close", (event) => {
    // 三个字段一起保存,避免只凭关闭码猜原因。
    const record = {
      code: event.code,
      wasClean: event.wasClean,
      reason: event.reason || "",
    };

    // reason 可能为空,日志系统不要把空原因当成新的异常。
    console.info("WebSocket closed", record);
  });
}

这里没有把 reason 当作机器可识别的状态。它是对端或子协议提供的人类可读说明,可能为空,也可能只在服务端主动发送关闭帧时有内容。代码判断应依赖 code 和 wasClean,日志里再保留 reason 方便排查。

常见关闭码分别说明什么

关闭码不是 HTTP 状态码,连接升级成功后要按 WebSocket 协议的关闭码理解。下面列出前端排查中最常遇到的一组,重点是它们对客户端动作的提示。

关闭码通常含义前端判断重点
1000Normal Closure,正常关闭通常不需要报警或重连,先确认是否由页面主动调用了 close()。
1001Going Away,端点离开可能是页面离开、浏览器环境结束或服务端准备下线,结合页面生命周期判断。
1006Abnormal Closure,异常关闭表示没有收到正常关闭状态,不能由应用主动发送;重点检查网络、代理、服务端进程和握手结果。
1008Policy Violation,策略违规通常需要看鉴权、权限、消息规则或服务端策略,不应盲目快速重连。
1009Message Too Big,消息过大缩小消息、拆分传输或调整协议边界,而不是把它当成临时网络抖动。
1011Internal Error,服务端内部错误保留 reason 和请求上下文,重连前先考虑服务端是否仍处于故障状态。
WebSocket 常见关闭码按可预期结束和协议运行异常分组的静态说明图
图2:常见 WebSocket 关闭码的判断边界说明图,不表示某次真实连接的执行流程。

其中最容易误解的是 1006。它是异常关闭的保留值,浏览器在没有拿到正常关闭状态时可以把它报告给脚本,但它不是一个应该由客户端调用 close(1006) 发送给服务端的业务码。遇到它,结论应是“关闭握手没有完整完成”,而不是直接断言“服务端一定宕机”。

用 wasClean 和 code 组合判断

如果只判断 event.code === 1000,会漏掉服务端用其他合法码完成关闭的情况;如果只判断 !event.wasClean,又会丢失策略拒绝、消息过大等处理方向。可以先把当前页面是否正在主动离开作为上下文,再做关闭码分级。

function classifyClose(event, pageLeaving) {
  // 页面离开时的 1001 不应和业务连接故障混在一起。
  if (pageLeaving && (event.code === 1000 || event.code === 1001)) {
    return "expected-page-leave";
  }

  // 1000 是正常关闭;wasClean 是对关闭握手是否完整的补充证据。
  if (event.code === 1000 && event.wasClean) {
    return "normal";
  }

  // 1006 不能直接发送,通常表示没有拿到正常关闭状态。
  if (event.code === 1006 || !event.wasClean) {
    return "transport-or-handshake-failure";
  }

  // 这些码已经给出较明确的处理方向,不要统一当成网络抖动。
  if (event.code === 1008) return "policy-rejected";
  if (event.code === 1009) return "message-too-large";
  if (event.code === 1011) return "server-internal-error";

  // 未覆盖的合法码先保留原值,交给业务日志继续分析。
  return "other-close-code";
}

这个函数的关键不是把所有场景都命名完,而是把“异常传输”和“有明确协议含义的拒绝”分开。对未知码保留原始数字,方便服务端和前端版本升级后继续对照协议登记表。

把分类结果接到 close 处理函数

有了分类结果之后,处理动作可以保持克制:正常结束只清理资源;页面离开不触发提示;传输类异常才进入受控重连;策略和消息边界错误则先记录并提示用户或开发者。

function handleSocketClose(event, state) {
  const kind = classifyClose(event, state.pageLeaving);

  // 无论原因是什么,先停止依赖当前连接的定时任务。
  clearInterval(state.heartbeatTimer);
  state.connected = false;

  switch (kind) {
    case "normal":
    case "expected-page-leave":
      // 正常离开不弹错误,也不创建新的连接。
      return { action: "stop", code: event.code };
    case "policy-rejected":
      // 鉴权或业务策略未通过时,重连通常不会改变结果。
      return { action: "show-policy-message", code: event.code };
    case "message-too-large":
      // 先修正消息大小,再决定是否恢复连接。
      return { action: "reduce-payload", code: event.code };
    case "server-internal-error":
    case "transport-or-handshake-failure":
      // 交给带退避和上限的重连器,避免连续打满服务端。
      return { action: "schedule-reconnect", code: event.code };
    default:
      // 未知关闭码只记录,不在这里做激进的自动修复。
      return { action: "record-and-review", code: event.code };
  }
}

示例中的 schedule-reconnect 只是动作名,不代表应该立即循环创建连接。实际项目要给重连设置退避、次数上限和页面可见性条件,并且在鉴权失败或消息过大时停止自动重试。

这几种现象怎样快速定位

遇到断开时,可以按下面顺序读现场信息,避免把不同原因混成“WebSocket 不稳定”。

  • 1000 且 wasClean 为 true:先查是谁主动调用了 close(),或服务端是否按正常流程结束连接。
  • 1001:对照页面的 pagehide、路由切换、浏览器关闭和服务端下线事件;它表达的是端点离开,不等同于代码报错。
  • 1006 且 wasClean 为 false:把连接建立时间、最后一条消息、网络切换、代理日志和服务端进程状态放在同一时间窗口里对比;不要只根据一个码下结论。
  • 1008、1009、1011:优先阅读 reason 和服务端日志,分别从策略、消息尺寸、服务端内部错误方向处理。

另外,error 事件通常只告诉前端发生了错误,具体关闭信息仍要在 close 事件里读取。两个监听器都保留,才能知道“先报错后关闭”是否和连接异常对应。

最后确认:什么才算正常断开

可以把判断浓缩成一句话:1000 + wasClean=true 是最典型的正常结束;1001 需要结合端点是否离开;1006 + wasClean=false 说明没有完成正常关闭握手;1008、1009、1011 则分别给出策略、消息尺寸和服务端错误方向。

写日志时至少保留 code、wasClean、reason、页面动作和连接持续时间。这样下一次出现异常断开时,前端可以先完成正确分级,再决定是否重连,而不是看到一个 1006 就反复刷新页面。

相关问题

  • WebSocket 的 1006 能不能在客户端主动发送?
  • 为什么 WebSocket 关闭时 reason 为空?
  • 1008 和 1011 都出现时应该先查哪里?
  • WebSocket 异常断开时怎样避免无限重连?
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
URLSearchParams 加号与空格编码的处理方法URLSearchParams 加号与空格编码的处理方法
上一篇
URLSearchParams 加号与空格编码的处理方法
Vite 环境变量为什么需要 VITE_ 前缀
下一篇
Vite 环境变量为什么需要 VITE_ 前缀
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    992次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    996次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1118次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1092次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    934次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码