websocket网络通信协议

websocket网络通信协议

参考:websocket_rfc6455

网络:

  • 网络编程:解决1对多通信问题(1个server对N个client)
    • epoll
    • reactor
  • 网络协议:解决一个客户端与一个服务器的通信问题
    • http
    • websocket

websocket

基于tcp的协议,解决粘包和拆包问题.

websocket头

WebSocket 的头信息结构需区分握手阶段 (基于 HTTP 协议)和数据传输阶段(WebSocket 帧格式),两者的结构差异较大:

一、握手阶段:基于 HTTP 头信息

WebSocket 握手是通过 HTTP 协议完成的(客户端发送 HTTP 请求,服务器返回 HTTP 响应),因此头信息遵循 HTTP 格式,核心字段如下:

1. 客户端握手请求头(HTTP GET 请求)
http 复制代码
GET /chat HTTP/1.1
Host: example.com:8080
Upgrade: websocket                  // 核心:请求升级到 WebSocket 协议
Connection: Upgrade                 // 配合 Upgrade,表示连接要升级
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==  // 随机字符串,用于服务器验证
Sec-WebSocket-Version: 13           // 客户端支持的 WebSocket 版本(当前标准为 13)
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits  // 可选:协商扩展(如压缩)
Sec-WebSocket-Protocol: chat, superchat  // 可选:协商子协议(应用层自定义协议)
Origin: http://example.com          // 可选:客户端来源(用于服务器跨域验证)

关键字段说明:

  • Upgrade: websocket + Connection: Upgrade:强制触发 HTTP 协议升级机制,声明要从 HTTP 切换到 WebSocket。
  • Sec-WebSocket-Key:16 字节随机值的 Base64 编码,用于服务器生成 Sec-WebSocket-Accept 进行验证(防止误判非 WebSocket 响应)。
  • Sec-WebSocket-Version: 13:指定 WebSocket 版本(13 是当前标准,早期版本如 8、10 已淘汰)。
2. 服务器握手响应头(101 状态码)
http 复制代码
HTTP/1.1 101 Switching Protocols    // 核心:确认协议升级
Upgrade: websocket                  // 呼应客户端,确认升级到 WebSocket
Connection: Upgrade                 // 确认连接保持升级状态
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=  // 服务器验证后的密钥(基于客户端 Key + GUID 计算)
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits  // 可选:确认支持的扩展
Sec-WebSocket-Protocol: chat        // 可选:确认使用的子协议(从客户端请求中选择)

关键字段说明:

  • 101 Switching Protocols:HTTP 状态码,表示服务器同意协议升级。
  • Sec-WebSocket-Accept:服务器通过"客户端 Key + 固定 GUID(258EAFA5-E914-47DA-95CA-C5AB0DC85B11)"拼接后,经 SHA-1 哈希 + Base64 编码生成,客户端会验证此值以确认服务器支持 WebSocket。

二、数据传输阶段:WebSocket 帧(Frame)头结构

握手完成后,数据传输使用二进制帧格式,每个帧的头信息是二进制结构(而非文本 HTTP 头),格式如下(单位:bit):

字段 位数 含义
FIN 1 是否为"最后一帧":1 = 该帧是消息的最后一部分;0 = 后续还有帧(用于分片消息)。
RSV1-3 1-1-1 保留位,用于扩展协议(如压缩),未使用时必须为 0,否则接收方会断开连接。
Opcode 4 帧类型: - 0x0:延续帧(分片消息的中间帧) - 0x1:文本帧(数据为 UTF-8 编码) - 0x2:二进制帧(任意二进制数据) - 0x8:关闭连接帧 - 0x9:Ping 帧(心跳检测) - 0xA:Pong 帧(Ping 响应)
Mask 1 是否使用掩码:1 = 帧数据被掩码加密(客户端发送的帧必须设为 1);0 = 未加密(服务器发送的帧必须设为 0)。
Payload Length 7 / 7+16 / 7+64 有效载荷(数据)长度: - 若值 ≤ 125:直接表示长度(单位:字节)。 - 若值 = 126:后续 2 字节(16 位无符号整数)表示长度。 - 若值 = 127:后续 8 字节(64 位无符号整数)表示长度。
Masking Key 0 / 32 掩码密钥:仅当 Mask=1 时存在(4 字节),用于解密 Payload Data(客户端发送的数据必须用此密钥加密)。
Payload Data 可变 实际传输的数据(文本/二进制/控制信息),长度由 Payload Length 指定。
帧头示例(简化):

假设客户端发送一个 10 字节的文本帧(完整消息,非分片):

  • FIN=1(最后一帧)
  • RSV1-3=000(无扩展)
  • Opcode=0x1(文本帧)
  • Mask=1(客户端发送,需掩码)
  • Payload Length=10(≤125,直接表示)
  • Masking Key=0x12345678(4 字节随机密钥)
  • Payload Data=10字节文本数据(经掩码加密)

总结

WebSocket 的"头信息"分两个阶段:

  1. 握手阶段 :基于 HTTP 文本头,核心是通过 Upgrade 等字段完成协议升级和验证(确保双方支持 WebSocket)。
  2. 数据阶段 :使用二进制帧头,通过 FIN、Opcode、Payload Length 等字段定义数据传输规则(如消息分片、数据类型、长度等),并通过掩码保证客户端发送数据的安全性。

这种设计既兼容了 HTTP 基础设施(握手阶段),又实现了高效的全双工数据传输(帧结构阶段)。

websocket面试题

为什么websocket要握手?

WebSocket 握手(Handshake)是从 HTTP 协议"升级"到 WebSocket 协议的关键过程,其核心目的是在 HTTP 基础设施(如代理、防火墙、服务器)的兼容前提下,建立一个持久化的全双工通信通道。你提到的"版本升级""兼容 HTTP 协议""验证双方身份"是核心原因,具体细节如下:

1. 本质是"协议版本升级":从 HTTP 到 WebSocket

HTTP 是请求-响应模式的短连接协议 (每次通信需客户端主动发起请求),而 WebSocket 是全双工的长连接协议(客户端和服务器可随时双向发送数据)。两者的通信模式完全不同,因此需要通过"握手"完成协议切换:

  • 客户端发送HTTP 升级请求,明确告知服务器:"我想从 HTTP 切换到 WebSocket 协议",并携带 WebSocket 相关参数(如版本号、支持的扩展等)。
  • 服务器若支持 WebSocket,会返回101 Switching Protocols响应,确认"同意升级",从此连接不再遵循 HTTP 规则,而是使用 WebSocket 帧格式传输数据。

这一步是"版本升级"的核心:通过 HTTP 协议的"Upgrade"机制,完成从短连接到长连接、从单向请求到双向通信的转换。

2. 兼容 HTTP 协议:穿透现有网络基础设施

WebSocket 设计时必须兼容现有基于 HTTP 的网络环境(如代理服务器、负载均衡器、防火墙等),否则会被这些中间设备拦截或误处理。握手的关键作用就是"伪装"成 HTTP 流量,通过基础设施的验证:

  • 握手过程完全使用 HTTP 报文格式(如 GET 请求方法、Host 头、Upgrade 头),让中间设备误认为这是一个普通 HTTP 请求,从而允许其通过。
  • 只有完成握手后,通信才切换到 WebSocket 帧格式,但此时连接已建立,中间设备通常不会再拦截长连接的后续数据。

若没有握手过程,直接使用全新的协议格式,会被大多数 HTTP 代理/防火墙阻断(它们只允许 HTTP 标准流量),导致 WebSocket 无法在现有网络中普及。

3. 验证双方"协议能力":确保通信参数一致

握手过程包含简单的"验证机制",核心是确认双方都理解并支持 WebSocket 协议,避免误连接(如客户端连接到不支持 WebSocket 的 HTTP 服务器):

  • 客户端发送 Sec-WebSocket-Key(一个随机字符串),服务器需通过特定算法(SHA-1 哈希 + Base64 编码)计算出 Sec-WebSocket-Accept 并返回。
  • 客户端验证服务器返回的 Sec-WebSocket-Accept 是否正确,若正确则确认"服务器确实支持 WebSocket",否则断开连接。

这个验证不是"身份认证"(不涉及用户身份),而是"协议能力验证",确保双方在同一套规则下通信。此外,握手时还会协商:

  • WebSocket 版本(Sec-WebSocket-Version),避免版本不兼容;
  • 支持的扩展(Sec-WebSocket-Extensions)和子协议(Sec-WebSocket-Protocol),确定数据压缩、自定义协议等细节。
总结

WebSocket 握手是一个"一举三得"的设计:

  • 通过协议升级,从 HTTP 短连接转换为 WebSocket 长连接;
  • 借助HTTP 兼容,穿透现有网络基础设施(代理、防火墙等);
  • 通过协议验证,确保双方支持相同的 WebSocket 规则,避免无效连接。

这使得 WebSocket 既能享受长连接全双工的优势,又能在现有 HTTP 生态中无缝部署,成为实时通信(如聊天、弹幕、实时数据更新)的主流方案。

websocket握手为什么要GUID?

避免数据太短,无法hash.

WebSocket 握手过程中引入固定 GUID(258EAFA5-E914-47DA-95CA-C5AB0DC85B11)的核心目的,并非单纯"避免数据太短无法哈希",而是通过标准化的固定字符串,确保握手验证的唯一性和安全性,防止"误判"或"跨协议攻击"。

具体背景:握手验证的流程

WebSocket 握手的验证逻辑是:

  1. 客户端生成一个 16 字节的随机值,用 Base64 编码后作为 Sec-WebSocket-Key 发送给服务器。
  2. 服务器将这个 Sec-WebSocket-Key 与固定 GUID 拼接,得到一个新字符串。
  3. 对新字符串做 SHA-1 哈希 ,再将哈希结果用 Base64 编码,得到 Sec-WebSocket-Accept,返回给客户端。
  4. 客户端重复服务器的计算过程,验证返回的 Sec-WebSocket-Accept 是否一致,一致则确认握手成功。
GUID 的核心作用:防止"误匹配"

如果没有这个固定 GUID,验证逻辑会存在严重漏洞:

  • 假设客户端发送的 Sec-WebSocket-Key 是一个随机字符串,服务器只需对其进行某种哈希处理后返回。
  • 但此时可能出现**"巧合匹配"**:比如客户端误将一个普通 HTTP 服务器的响应(非 WebSocket 握手)当作 valid 验证结果(例如,服务器返回的某个字符串恰好与客户端的哈希计算结果一致)。

而固定 GUID 的引入,相当于给验证过程加了一个**"唯一标识符"**:

  • 只有知道这个 GUID 的服务器(即真正支持 WebSocket 协议的服务器),才能生成正确的 Sec-WebSocket-Accept。
  • 普通 HTTP 服务器或其他协议的服务器不知道这个 GUID,无法生成匹配的响应,客户端就能明确区分"真正的 WebSocket 服务器"和"其他服务器"。
关于"数据长度"的补充

客户端发送的 Sec-WebSocket-Key 是 16 字节随机值(Base64 编码后为 24 字符),这个长度本身足够进行 SHA-1 哈希(SHA-1 可处理任意长度数据,哪怕只有 1 字节)。

因此,"避免数据太短"是次要因素,真正核心是通过固定 GUID 确保验证逻辑的"协议唯一性"------只有遵循 WebSocket 标准的服务器才能通过验证,从根本上杜绝跨协议的误判风险。

总结

WebSocket 握手引入固定 GUID,是为了给验证过程增加一个**"协议专属密钥"**:

  • 确保服务器确实理解 WebSocket 协议(知道这个 GUID),而非其他协议的服务器。
  • 彻底避免因随机巧合导致的"误验证",保证握手的安全性和准确性。

这个设计让 WebSocket 在兼容 HTTP 基础设施的同时,又能可靠地区分协议类型,是协议设计中"安全性与兼容性平衡"的典型案例。

相关推荐
贞明电子13 小时前
工业三色报警灯怎么接入项目系统?开关量与RS485控制应用指南
运维·网络·微信公众平台·贞明电子
明天也要努力学习13 小时前
HTTP 协议的基本格式和 fiddler 的用法
网络协议·http·fiddler
HideF14 小时前
Linux
linux·服务器·网络
万联WANFLOW14 小时前
海外网络故障怎么排查?Cloudflare 三季度断网报告解读与 mtr 实战
运维·网络·故障分析
sbjdhjd14 小时前
网工进阶笔记:H3CSE 园区网全栈技术与协议汇总
网络·笔记·云计算·ssh·网络工程·vlan·aaa
taktok_ai16 小时前
用 cc-switch 连接 Taktok
网络
小嘉丶学长18 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节
pt104320 小时前
Cisco设备网络安全系列-18:SIEM与SOAR安全解决方案
网络·安全
Tel1992530800420 小时前
温度湿度信号转WiFi/MQTT/Modbus TCP采集模块 无线传输
网络·网络协议·tcp/ip·工业自动化·工控设备
yyuuuzz21 小时前
云服务器安全组规则优先级的机制记录
运维·服务器·网络·安全·阿里云·aws