概述
为什么需要 WebSocket
HTTP
的局限性:- 传统
HTTP
是无状态、短连接的协议,客户端必须主动发起请求才能获取数据,无法实现服务端主动推送数据
- 传统
- 实时性需求:
- 在线聊天、实时游戏、金融行情等场景需要双向、低延迟的通信,
WebSocket
应运而生
- 在线聊天、实时游戏、金融行情等场景需要双向、低延迟的通信,
WebSocket
的特点
- 全双工通信:客户端和服务端可以同时发送数据
- 长连接:建立连接后持续保持,避免重复握手
- 低开销:数据传输格式轻量,头部开销小
- 基于
TCP
:工作在TCP
协议之上,默认端口80
(WS
)或443
(WSS
)
问题与理解
HTTP2
就可以实现服务端主动推送数据,和WebSocket
相比?HTTP/2
的Server Push
是为了优化网页加载性能,允许服务端在客户端请求某个资源(如HTML
)时,提前推送相关资源(如CSS
、JS
、图片),减少客户端后续的请求延迟- 比如,客户端请求
index.html
,服务端返回HTML
的同时,主动推送style.css
和app.js
,无需客户端再次请求 - 总结来说,
HTTP2
的服务端推送是HTTP
协议的优化手段,用于静态资源预加载,无法实现真正的服务端主动推送动态数据 - 而
WebSocket
是独立的通信协议,专为全双工实时通信设计,适合需要服务端主动推送动态数据的场景
WebSocket
协议的工作流程
握手阶段(Handshake
)
- 客户端发起请求:通过
HTTP
的Upgrade
头申请协议升级
1 2 3 4 5 6 |
GET /chat HTTP/1.1 Host: example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 |
- 服务端响应:返回状态码
101 Switching Protocols
,完成握手
1 2 3 4 |
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= |
数据传输阶段
- 数据帧(
Frame
):WebSocket
将数据分割为帧(Frame
)传输,帧结构包括:FIN
:标识是否为消息的最后一帧Opcode
:定义数据类型(如文本、二进制、关闭帧等)Mask
:客户端发送的数据需掩码加密Payload
:实际传输的数据
WebSocket
协议的优势
实时性
- 服务端可主动推送数据,无需客户端轮询
低延迟
- 长连接避免了频繁的
TCP
握手和HTTP
头开销
跨域支持
- 可通过
Origin
头实现安全的跨域通信
兼容性
- 现代浏览器均支持
WebSocket API
应用场景
实时通信
- 在线聊天、视频会议(如
Slack
、Zoom
)
实时数据推送
- 股票行情、体育赛事比分
多人在线游戏
- 同步玩家状态和操作
物联网(IoT
)
- 设备状态监控与控制
客户端实现(Javascript
示例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// 创建 WebSocket 连接 const socket = new WebSocket('wss://example.com/chat'); // 监听事件 socket.onopen = () => { console.log('连接已建立'); socket.send('Hello Server!'); }; socket.onmessage = (event) => { console.log('收到消息:', event.data); }; socket.onerror = (error) => { console.error('发生错误:', error); }; socket.onclose = () => { console.log('连接已关闭'); }; |
服务端实现(Node.js
示例,ws
库)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', (ws) => { console.log('客户端已连接'); ws.on('message', (message) => { console.log('收到消息:', message); ws.send(`服务器回复: ${message}`); }); ws.on('close', () => { console.log('客户端已断开'); }); }); |
注意事项
安全性
- 使用
wss://
(WebSocket Secure
)替代ws://
,通过TLS
加密数据 - 验证
Origin
头防止跨站劫持(CSRF
)
心跳机制
- 定期发送
Ping/Pong
帧检测连接活性,避免超时断开
错误处理
- 监听
onerror
和onclose
事件,实现自动重连逻辑
兼容性
- 部分旧浏览器不支持
WebSocket
,可降级为长轮询(Long Polling
)方案
和HTTP/2对比
设计目标
特性 | WebSocket |
HTTP/2 |
核心目标 | 实现 全双工实时双向通信 | 优化 HTTP/1.x 性能,支持多路复用和资源推送 |
适用场景 | 实时聊天、游戏、高频数据交互 | 网页加载优化、减少延迟、提升资源加载效率 |
协议层级 | 独立协议(基于 TCP ) |
HTTP 协议的进化版本(基于 TCP ) |
通信模式
特性 | WebSocket |
HTTP/2 |
连接方式 | 长连接:一次握手后保持连接,双向通信 | 短连接:默认复用 TCP 连接,但仍是请求-响应模型 |
数据方向 | 全双工:客户端和服务端可随时互发数据 | 半双工:客户端发起请求,服务端响应(即使开启 Server Push ,推送仍依赖初始请求) |
主动推送 | 服务端可随时主动推送数据 | 服务端只能推送预关联的资源(如 CSS 、JS ),无法动态推送业务数据 |
性能对比
特性 | WebSocket |
HTTP/2 |
头部开销 | 数据帧头部仅 2-14 字节(轻量) |
使用 HPACK 压缩头部,但仍需携带 HTTP 元数据 |
延迟 | 极低(长连接避免重复握手) | 较低(多路复用减少连接数,但请求仍需等待响应) |
并发能力 | 高(单连接支持双向实时流) | 高(多路复用支持并行请求,但受限于流控制) |
协议功能
特性 | WebSocket |
HTTP/2 |
数据格式 | 支持 文本和二进制帧,灵活性强 | 仅支持 HTTP 兼容的请求-响应数据格式 |
状态管理 | 无状态(需自行实现会话逻辑) | 无状态(依赖 Cookie 或 Token 等机制) |
推送机制 | 动态推送任意数据(如聊天消息) | 仅推送静态资源(如 CSS 、JS ),需预先关联 |
安全性
特性 | WebSocket |
HTTP/2 |
加密支持 | 支持 wss:// (基于 TLS ) |
强制要求 TLS 加密(主流浏览器仅支持 HTTPS ) |
跨域控制 | 依赖 Origin 头验证 |
同源策略(CORS ) |
攻击防护 | 需自行处理消息注入、DoS 等 |
依赖 HTTP 安全机制(如 CSP 、HSTS ) |
应用场景对比
场景 | WebSocket 更优 |
HTTP/2 更优 |
实时聊天 | ✅ 全双工通信,服务端主动推送消息 | ❌ 只能轮询或依赖 SSE (单向) |
在线游戏 | ✅ 实时同步玩家状态和操作 | ❌ 无法满足高频双向交互需求 |
股票行情 | ✅ 实时推送价格变动 | ❌ 需客户端轮询或依赖 SSE (单向) |
网页加载 | ❌ 不适用 | ✅ 多路复用和 Server Push 优化资源加载 |
API 交互 |
❌ 复杂且不必要 | ✅ 适合 RESTful API 或 GraphQL |
和HPPT/3
对比
协议基础对比
特性 | WebSocket |
HTTP/3 |
底层协议 | 基于 TCP |
基于 QUIC (UDP 协议) |
核心目标 | 实现全双工实时双向通信 | 优化 HTTP 性能,解决 TCP 的队头阻塞问题 |
连接建立速度 | 依赖 TCP 握手 + WebSocket 握手 |
0-RTT 或 1-RTT (QUIC 快速握手) |
数据可靠性 | 可靠传输(基于 TCP ) |
可靠传输(QUIC 内置可靠性) |
多路复用 | 单连接支持双向流 | 原生多路复用,无队头阻塞 |
通信模式
特性 | WebSocket |
HTTP/3 |
通信方向 | 全双工:客户端和服务端可随时互发数据 | 半双工:仍是 HTTP 请求-响应模型 |
服务端主动推送 | ✅ 支持动态数据实时推送 | ❌ 仅支持 HTTP/2 类似的 Server Push (预加载静态资源) |
实时性 | 毫秒级延迟(长连接无握手开销) | 延迟较低(QUIC 减少握手和队头阻塞) |
数据格式 | 支持文本、二进制帧 | 仅支持 HTTP 兼容的请求-响应数据格式 |
性能对比
特性 | WebSocket |
HTTP/3 |
抗丢包能力 | 依赖 TCP 重传机制 |
✅ QUIC 改进的拥塞控制和前向纠错(FEC ) |
移动网络适应性 | 一般(TCP 队头阻塞影响) |
✅ 更优(UDP + 多路复用避免队头阻塞) |
头部开销 | 帧头 2-14 字节 |
✅ QPACK 压缩头部(类似 HTTP/2 ) |
连接迁移能力 | ❌ 切换网络需重新连接 | ✅ QUIC 支持连接 ID ,网络切换无感 |
安全性
特性 | WebSocket |
HTTP/3 |
加密强制要求 | wss:// 强制 TLS 加密 |
✅ 所有 HTTP/3 连接必须使用 TLS 1.3+ |
抗中间人攻击 | 依赖 TLS 加密 |
✅ QUIC 内置加密,握手过程更安全 |
跨域控制 | 依赖 Origin 头验证 |
同源策略(CORS ) |
应用场景对比
场景 | WebSocket 更优 |
HTTP/3 更优 |
实时聊天/游戏 | ✅ 双向实时通信 | ❌ 无法主动推送动态数据 |
视频直播/会议 | ✅ 低延迟音视频流 | ❌ 需依赖 WebRTC 或其他协议 |
高频 API 交互 |
❌ 不适合(需维护长连接) | ✅ 多路复用提升效率 |
弱网环境(如移动端) | ❌ TCP 队头阻塞可能影响性能 |
✅ QUIC 抗丢包和快速重连优势明显 |
静态资源加载 | ❌ 不适用 | ✅ Server Push 预加载优化 |
与 WebTransport
的关系
- 概述
HTTP/3
的QUIC
协议催生了WebTransport
,这是一个新兴的API
,旨在弥补HTTP
在实时通信中的不足
WebTransport
的特性:- 基于
HTTP/3
或QUIC
,支持可靠和不可靠数据传输 - 提供双向流(类似
WebSocket
)和多路复用 - 支持服务端主动推送,无需依赖
HTTP
请求
- 基于
WebSocket vs WebTransport
WebSocket
:成熟、全双工,但基于TCP
,队头阻塞问题仍在WebTransport
:基于QUIC
,解决队头阻塞,更灵活,但目前浏览器支持有限(Chrome
实验性支持)
和QUIC
对比
协议基础对比
特性 | WebSocket |
QUIC |
协议层级 | 应用层协议(基于 TCP ) |
传输层协议(基于 UDP ) |
核心目标 | 实现全双工实时双向通信 | 替代 TCP ,解决队头阻塞,提升传输效率 |
连接建立速度 | 依赖 TCP 三次握手 + WebSocket 握手 |
0-RTT 或 1-RTT (快速握手) |
数据可靠性 | 可靠传输(依赖 TCP ) |
可靠传输(QUIC 内置可靠性机制) |
多路复用 | 单连接支持双向流 | 原生多路复用,无队头阻塞 |
通信模式对比
特性 | WebSocket |
QUIC |
通信方向 | 全双工:客户端和服务端可随时互发数据 | 支持全双工,但需上层协议实现(如 HTTP/3 ) |
服务端主动推送 | ✅ 支持动态数据实时推送 | ❌ 需依赖应用层协议(如 HTTP/3 Server Push ) |
实时性 | 毫秒级延迟(长连接无握手开销) | 延迟更低(QUIC 减少握手和队头阻塞) |
数据格式 | 支持文本、二进制帧 | 传输字节流,数据格式由上层协议定义 |
性能对比
特性 | WebSocket |
QUIC |
抗丢包能力 | 依赖 TCP 重传机制 |
✅ 改进的拥塞控制和前向纠错(FEC ) |
移动网络适应性 | 一般(TCP 队头阻塞影响) |
✅ 更优(UDP + 多路复用避免队头阻塞) |
头部开销 | 帧头 2-14 字节 |
低开销(头部加密且优化) |
连接迁移能力 | ❌ 切换网络需重新连接 | ✅ 支持连接 ID ,网络切换无感 |
应用场景对比
场景 | WebSocket 更优 |
QUIC 更优 |
实时聊天/游戏 | ✅ 双向实时通信 | ❌ 需依赖上层协议(如 WebTransport ) |
视频直播/会议 | ✅ 低延迟音视频流(结合 WebRTC ) |
✅ 弱网环境下传输更稳定(如 QUIC + WebRTC ) |
高频 API 交互 |
❌ 不适合(需维护长连接) | ✅ 多路复用提升效率(如 HTTP/3 ) |
静态资源加载 | ❌ 不适用 | ✅ 资源加载更快(HTTP/3 over QUIC ) |
物联网设备通信 | ✅ 简单实时控制 | ✅ 适应网络波动(QUIC 快速重连) |
安全性对比
特性 | WebSocket |
QUIC |
加密强制要求 | wss:// 强制 TLS 加密 |
✅ 所有 QUIC 连接必须使用 TLS 1.3+ |
抗中间人攻击 | 依赖 TLS 加密 |
✅ 加密内置到协议设计(无法明文传输) |
握手安全性 | 依赖 TLS 握手 |
✅ 0-RTT 握手减少延迟,但需防重放攻击 |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ libcurl简述11/20
- ♥ Linux 高性能服务器编程:网络基础编程一11/27
- ♥ HTTP协议相关学习一03/22
- ♥ HTTP 协议10/22
- ♥ 【Javascript】对象构造05/20
- ♥ 【Javascript】第二部分05/14