← 中文资源

简体中文版本

WebSocket 协议

WebSocket 把一条 HTTP 连接升级为持久的双向消息通道,成帧开销极小,适合聊天、协作编辑、实时仪表盘与游戏状态同步。

阅读英文原文

概念定义

HTTP 由请求驱动:客户端问、服务器答。WebSocket 只协商一次,之后双方随时发送带帧的消息。帧头只有几字节,取代逐消息的完整 HTTP 语义,这才是效率来源。协议支持文本与二进制消息、ping-pong 保活与关闭语义。

工作机制

客户端发出带 Sec-WebSocket-Key 的 Upgrade 请求,服务器以 101 与证明摘要应答,连接随即切换协议。客户端到服务器的消息带掩码;ping、pong、close 等控制帧共用同一通道;子协议用于协商应用层消息模式。

使用场景

双向与高频流:聊天、协同编辑、多人游戏状态、遥测上报。纯服务器到客户端的场景用 SSE 更简单,还能享受 HTTP 缓存与自动重连。混合设计常用 HTTP 写入加 SSE 推送。

常见误区

消息仅在单连接内有序,跨重连的顺序保障是应用的责任。代理与负载均衡器会对无心跳的升级连接做空闲超时;故障后的重连风暴需要带抖动的退避。长寿命连接不应只信任升级时的认证,消息级确认也必须由应用实现。

代码示例

const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

function pad(value) {
  return String(value).padStart(2, "0");
}

export function formatHttpDate(date = new Date()) {
  const value = date instanceof Date ? date : new Date(date);
  if (Number.isNaN(value.getTime())) throw new RangeError("invalid date");
  return DAYS[value.getUTCDay()] + ", "
    + pad(value.getUTCDate()) + " "
    + MONTHS[value.getUTCMonth()] + " "
    + value.getUTCFullYear() + " "
    + pad(value.getUTCHours()) + ":"
    + pad(value.getUTCMinutes()) + ":"
    + pad(value.getUTCSeconds()) + " GMT";
}

export function parseHttpDate(input) {
  if (typeof input !== "string") throw new TypeError("input must be a string");
  const value = Date.parse(input);
  if (Number.isNaN(value)) throw new RangeError("invalid HTTP date");
  return new Date(value);
}
import { Agent, fetch } from 'undici';

const agent = new Agent({
  connections: 128,
  pipelining: 10,
  keepAliveTimeout: 60_000,
  keepAliveMaxTimeout: 300_000,
});

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 5000);

const res = await fetch('https://api.example.com/users', {
  dispatcher: agent,
  signal: controller.signal,
});
const users = await res.json();
clearTimeout(timer);

agent.close();