WebSocket 通信协议详细解析

目录

概述

[1 协议介绍](#1 协议介绍)

[1.1 协议基础](#1.1 协议基础)

[1.2 协议握手流程(核心)](#1.2 协议握手流程(核心))

[2 核心:WebSocket 数据帧格式](#2 核心:WebSocket 数据帧格式)

[2.1 帧结构](#2.1 帧结构)

[2.2 关键字段详解](#2.2 关键字段详解)

[2.3 帧传输规则](#2.3 帧传输规则)

[3 连接和传输管理](#3 连接和传输管理)

[3.1 连接管理](#3.1 连接管理)

[3.2 协议安全与扩展](#3.2 协议安全与扩展)

[4 WebSocket 与 HTTP 协议的核心区别](#4 WebSocket 与 HTTP 协议的核心区别)

[5 总结](#5 总结)


概述

WebSocket 是由 IETF 标准化的全双工、低开销、基于 TCP 的应用层通信协议 ,标准文档为 RFC 6455 ,其核心目标是解决 HTTP 协议 "客户端单向请求、服务器无法主动推送" 的痛点,实现客户端与服务器的实时双向持久通信。以下从协议底层机制、核心流程、帧结构等维度进行深度拆解。

1 协议介绍

1.1 协议基础

1) 核心特性

  • 全双工通信:连接建立后,客户端和服务器可同时收发数据,无需等待对方响应。
  • 持久连接:一次握手后保持 TCP 连接,避免 HTTP 短连接的频繁三次握手开销。
  • 低数据开销:数据传输阶段无需携带 HTTP 头,仅需少量帧协议开销(相比 HTTP 1.1 的请求头体积大幅降低)。
  • 跨域支持:原生支持跨域通信,依赖服务器配置跨域规则即可。
  • 二进制支持:可直接传输文本(UTF-8)和二进制数据(如文件、音视频流)

2) 协议架构

WebSocket 协议分为两层

  • 握手层:基于 HTTP 1.1 协议完成 "协议升级",是连接建立的桥梁。
  • 数据传输层:定义独立的帧格式,用于封装和传输数据。

1.2 协议握手流程(核心)

WebSocket 连接建立的核心是 HTTP 协议升级 ,整个过程为单次往返(客户端发请求,服务器回响应),无需额外交互。

1) 客户端发起升级请求

客户端向服务器发送 HTTP GET 请求 ,请求头必须包含以下关键字段,且请求方法只能是 GET,HTTP 版本至少为 1.1

字段名 取值 作用
Upgrade websocket 声明要升级的目标协议
Connection Upgrade 标识这是一个协议升级请求
Sec-WebSocket-Key 16 字节随机值的 Base64 编码 用于验证服务器合法性,防止伪造响应
Sec-WebSocket-Version 13 指定协议版本(RFC 6455 对应版本,主流浏览器均支持)
Sec-WebSocket-Extensions(可选) permessage-deflate 协商协议扩展(如数据压缩)
Sec-WebSocket-Protocol(可选) chat 协商应用层子协议(服务器可选择支持的子协议)

请求示例

bash 复制代码
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: chat, superchat

2) 服务器验证并返回响应

服务器收到请求后,需完成 3 个核心验证:

  • 检查 UpgradeConnection 字段是否为 websocketUpgrade
  • 检查 Sec-WebSocket-Version 是否为 13(不支持则返回 426 Upgrade Required);
  • 验证 Sec-WebSocket-Key 并生成 Sec-WebSocket-Accept

--1) Sec-WebSocket-Accept 计算规则

服务器执行以下步骤生成响应密钥:

  • 将客户端的 Sec-WebSocket-Key 与固定字符串 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 拼接;
  • 对拼接后的字符串做 SHA-1 哈希计算(得到 20 字节二进制数据);
  • 将哈希结果做 Base64 编码 ,得到 Sec-WebSocket-Accept 值。

计算示例

若客户端 Sec-WebSocket-KeydGhlIHNhbXBsZSBub25jZQ==,拼接固定字符串后哈希编码,最终得到 s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

--2) 服务器响应(HTTP 101 状态码)

验证通过后,服务器返回 HTTP 101 Switching Protocols 响应,响应头包含以下字段:

bash 复制代码
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: chat
  • 101 状态码:表示服务器同意切换协议;
  • Sec-WebSocket-Accept:上述计算结果,客户端会验证该值是否正确;
  • 其他字段:返回协商成功的扩展和子协议。

3) 握手成功后的状态切换

客户端验证 Sec-WebSocket-Accept 无误后,HTTP 连接正式切换为 WebSocket 连接,后续通信不再使用 HTTP 协议,而是基于 WebSocket 帧格式传输数据。

2 核心:WebSocket 数据帧格式

2.1 帧结构

WebSocket 数据传输的最小单位是帧(Frame),所有数据(文本、二进制、控制指令)都必须封装成帧发送。RFC 6455 定义的帧结构如下(单位:比特):

字段 比特数 作用
FIN 1 标识是否为消息的最后一帧:1 = 最后一帧,0 = 后续还有帧(分片传输)
RSV1~RSV3 各 1 保留位,仅在使用协议扩展时非 0,否则必须为 0(否则连接关闭)
Opcode 4 帧类型标识,核心取值见下表
Mask 1 标识负载数据是否加掩码:1 = 加掩码(客户端→服务器必须为 1),0 = 无掩码(服务器→客户端必须为 0)
Payload length 7 / 7+16 / 7+64 负载数据长度,分三种编码方式
Masking-key 0 / 32 掩码密钥,仅当 Mask=1 时存在,共 4 字节
Payload data 可变 实际传输的数据:负载数据 + 扩展数据(可选)

2.2 关键字段详解

1) Opcode(帧类型): 这是帧的核心标识,决定了帧的用途,主流取值:

Opcode 值 帧类型 说明
0x00 延续帧 用于分片传输的非第一帧,需配合 FIN 位使用
0x01 文本帧 负载数据为 UTF-8 编码的文本
0x02 二进制帧 负载数据为任意二进制数据
0x08 关闭帧 用于关闭连接,负载数据包含关闭状态码和原因
0x09 Ping 帧 心跳检测请求,服务器收到后必须回复 Pong 帧
0x0A Pong 帧 心跳检测响应,对应 Ping 帧

(2)Payload length(负载长度编码)

为了节省空间,长度字段采用可变长度编码

  • 若长度 ≤ 125:直接用 7 比特表示,取值即长度;
  • 若 126 ≤ 长度 ≤ 65535:7 比特设为 126,后续 16 比特表示实际长度;
  • 若长度 > 65535:7 比特设为 127,后续 64 比特表示实际长度。

(3)Masking-key(掩码机制)

  • 强制要求 :客户端发送给服务器的所有帧必须加掩码(Mask=1),服务器发送的帧必须不加掩码;
  • 作用:防止恶意客户端构造特定数据,导致中间设备(如代理)缓存污染;
  • 解码规则 :负载数据的每个字节与掩码密钥的 4 字节循环异或,公式:decoded_byte = encoded_byte XOR masking_key[index % 4]

2.3 帧传输规则

  • 分片传输 :大消息可拆分为多个帧,仅最后一帧的 FIN=1,其余帧 FIN=0Opcode=0x00
  • 控制帧优先级 :Ping/Pong/ 关闭帧必须是单帧(FIN=1),且不能被分片,需优先传输;
  • 数据顺序:帧的传输顺序与接收顺序一致,服务器和客户端需按序拼接分片。

3 连接和传输管理

3.1 连接管理

1) 连接状态机

WebSocket 连接生命周期分为 3 个状态:

  • CONNECTING:握手进行中,尚未完成协议升级;
  • OPEN:连接已建立,可正常收发数据;
  • CLOSED:连接已关闭,无法传输数据。

2) 连接关闭流程

WebSocket 关闭连接需遵循双向握手机制,避免数据丢失,流程如下:

  • 发起方(客户端 / 服务器)发送 关闭帧(Opcode=0x08) ,负载数据包含关闭状态码 (2 字节)和原因字符串(UTF-8 可选);
  • 接收方收到关闭帧后,必须回复相同的关闭帧
  • 双方均发送并收到关闭帧后,关闭底层 TCP 连接

常见关闭状态码(RFC 6455 定义):

状态码 含义 场景
1000 正常关闭 连接完成预期目的后关闭
1001 端点离开 客户端关闭页面 / 服务器重启
1002 协议错误 收到非法帧或不符合协议的操作
1003 不支持的数据类型 收到不支持的 Opcode 帧
1006 异常关闭 未发送关闭帧直接断开 TCP 连接

3)心跳机制(Ping/Pong)

为了检测连接是否存活,WebSocket 定义了 Ping/Pong 心跳机制:

  • 一方发送 Ping 帧(Opcode=0x09),负载数据可选;
  • 另一方必须在合理时间内回复 Pong 帧(Opcode=0x0A),且 Pong 帧的负载数据必须与 Ping 帧一致;
  • 若未收到 Pong 响应,可判定连接异常,触发重连逻辑。

3.2 协议安全与扩展

1) 安全传输:WSS 协议

WebSocket 有两种传输模式:

  • ws://:明文传输,基于 TCP,端口通常为 80;
  • wss://:加密传输,基于 TCP + TLS/SSL,端口通常为 443。

生产环境必须使用 wss://,原因:

  • 防止数据被中间人窃听、篡改;
  • 避免部分网络环境(如防火墙)拦截 ws:// 连接;
  • 与 HTTPS 一致的安全级别,符合浏览器的安全策略。

2) 协议扩展

RFC 6455 支持通过 Sec-WebSocket-Extensions 协商扩展功能,主流扩展:

  • permessage-deflate:对整个消息进行压缩,降低传输带宽;
  • x-webkit-deflate-frame:早期浏览器的压缩扩展,已被 permessage-deflate 取代。

4 WebSocket 与 HTTP 协议的核心区别

特性 WebSocket HTTP 1.1
通信方向 全双工 半双工(客户端请求→服务器响应)
连接类型 持久连接 短连接(默认)/ 长连接(Connection: keep-alive)
数据开销 帧头开销小(几字节) 每次请求需携带完整 HTTP 头(数百字节)
服务器推送 支持主动推送 不支持,需依赖轮询 / 长轮询模拟
协议升级 基于 HTTP 升级 无升级机制
状态码 关闭帧状态码(1000+) 响应状态码(200/404/500 等)

5 总结

WebSocket 协议的核心设计思路是 "借 HTTP 握手,建 TCP 长连,用轻量帧传输",它不是替代 HTTP,而是对 HTTP 实时通信能力的补充。其帧格式的轻量化、全双工通信的高效性,使其成为实时聊天、物联网数据推送、在线游戏等场景的首选协议。

相关推荐
野指针YZZ1 小时前
TCP包 wireshark抓包分析-RK3588
网络·tcp/ip·wireshark
纽创信安2 小时前
纽创信安与SGS启动网络安全ISO 21434认证项目
网络·安全·web安全
MinterFusion2 小时前
如何在开放麒麟(openKylin)下安装FTP服务器(v0.1.0)
运维·服务器·网络·vsftpd·开放麒麟·明德融创·openkylin
Predestination王瀞潞3 小时前
5.2.1 通信->DNS域名系统协议标准(IETF RFC 1035):DNS(Domain Name System)
网络·网络协议·tcp/ip
帐篷Li3 小时前
【AgenticCPS 】CPS联盟返利系统 - 实施计划
大数据·网络·人工智能
Fly Wine4 小时前
IPsec 最简单场景总部和网关之间建立,并且流量不会全部经过总部
网络
GOU925 小时前
5101实验
网络·macos
IpdataCloud5 小时前
直播打赏异常排查:大额打赏IP来自高风险地区?用IP查询定位触发人工审核
网络·tcp/ip·网络安全·ip
riyue6665 小时前
封装 WebSocket 工具类
网络·vue.js·websocket·网络协议·v