SSE(Server-Sent Events)与 WebSocket 有什么区别?
维度WebSocketSSE设计目标全功能双向实时通道轻量级服务器推送协议开销极低(自定义帧结构)较高(HTTP头冗余)开发复杂度较高(需处理协议细节)较低(标准HTTP)数据能力二进制+文本仅文本断线恢复手动实现自动重连+消息追踪适用场景强交互应用单向数据广播📌终极建议需要双向交互 → WebSocket只需服务器推送+简单实现 → SSE兼容旧系统 → SSE + Polyfill。
SSE 与 WebSocket 核心区别全景解析
SSE(Server-Sent Events)和 WebSocket 都用于实现实时通信,但设计目标和技术实现有本质区别。以下是深度对比:

一、核心机制对比
| 特性 | WebSocket | SSE (Server-Sent Events) |
|---|---|---|
| 通信方向 | 全双工(双向实时通信) | 单工(仅服务器→客户端) |
| 协议基础 | 独立协议(HTTP升级后脱离HTTP) | 纯HTTP协议(长连接) |
| 数据格式 | 二进制帧或文本帧 | 纯文本(UTF-8) |
| 连接管理 | 需手动处理重连 | 自动重连(Retry机制) |
| 浏览器API | WebSocket 对象 |
EventSource 对象 |
| 首次连接 | HTTP 101切换协议 | 标准HTTP GET请求 |
二、工作流程详解
WebSocket 工作流程(双向通信)

SSE 工作流程(单向推送)

三、数据格式差异
WebSocket 帧结构(二进制灵活)
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +-+-+-+-+-------+-+-------------+ |F|R|R|R| opcode|M| Payload len | |I|S|S|S| (4) |A| (7) | |N|V|V|V| |S| | | |1|2|3| |K| | +-+-+-+-+-------+-+-------------+ | Extended payload length... +-------------------------------+ | Masking-key (if MASK set) +-------------------------------+ | Payload Data +--------------------------------
SSE 事件流格式(文本协议)
event: stockUpdate
id: 42
data: {"symbol":"AAPL","price":175.32}
retry: 5000
data: 系统将在5分钟后维护
: 注释行(客户端忽略)
-
字段说明:
-
event:事件类型(客户端监听特定事件) -
data:消息内容(可多行) -
id:事件ID(断线重连时用Last-Event-ID发送) -
retry:重连时间(毫秒)
-
四、性能与能力对比
| 维度 | WebSocket | SSE |
|---|---|---|
| 传输效率 | ⭐⭐⭐⭐⭐ (帧头2字节) | ⭐⭐ (HTTP头重复传输) |
| 延迟 | ⭐⭐⭐⭐⭐ (毫秒级) | ⭐⭐⭐ (依赖HTTP层) |
| 服务端推送 | ✅ 支持 | ✅ 支持 |
| 客户端发送 | ✅ 支持 | ❌ 需额外AJAX请求 |
| 二进制支持 | ✅ 原生支持 | ❌ 仅文本 |
| 自动重连 | ❌ 需手动实现 | ✅ 内置机制 |
| 压缩支持 | ✅ PerMessage-Deflate | ✅ HTTP压缩(gzip) |
| 最大并发连接数 | 不受限制(单连接复用) | 浏览器限制(Chrome 6-8个) |
五、代码实现对比
WebSocket 实现
// 客户端
const socket = new WebSocket('wss://api.example.com/ws');
socket.onmessage = (event) => {
console.log('Received:', event.data);
};
document.getElementById('send').addEventListener('click', () => {
socket.send(JSON.stringify({action: 'buy', stock: 'AAPL'}));
});
// 服务端(Node.js)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', (data) => {
console.log('Client says:', data);
});
setInterval(() => {
ws.send(JSON.stringify({price: Math.random()*100}));
}, 1000);
});
SSE 实现
// 客户端
const source = new EventSource('/events');
source.addEventListener('stockUpdate', (e) => {
console.log('Stock update:', e.data);
});
source.addEventListener('alert', (e) => {
alert(e.data);
});
// 服务端(Node.js/Express)
app.get('/events', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// 发送事件
setInterval(() => {
res.write(`event: stockUpdate\n`);
res.write(`data: ${JSON.stringify({symbol: "AAPL", price: getPrice()})}\n\n`);
}, 1000);
// 断线处理
req.on('close', () => {
clearInterval(interval);
});
});
六、选型决策指南

推荐场景:
| 技术 | 最佳适用场景 |
|---|---|
| WebSocket | 在线游戏、实时协作工具、聊天应用、金融交易平台 |
| SSE | 实时监控仪表盘、新闻推送、股票行情更新、社交媒体通知 |
七、关键注意事项
-
SSE的兼容性问题:
-
不支持IE(包括IE11)
-
部分浏览器限制并发SSE连接数(可通过域名分片解决)
-
-
WebSocket的复杂性:
-
需实现心跳保活机制
-
需处理二进制数据编解码
-
代理服务器可能导致连接问题(需WSS加密)
-
-
SSE的协议限制:
-
无法通过标准SSE发送Cookie(需URL参数传递认证信息)
-
最大连接时间限制(可搭配
retry字段自动恢复)
-
总结:核心区别精华
| 维度 | WebSocket | SSE |
|---|---|---|
| 设计目标 | 全功能双向实时通道 | 轻量级服务器推送 |
| 协议开销 | 极低(自定义帧结构) | 较高(HTTP头冗余) |
| 开发复杂度 | 较高(需处理协议细节) | 较低(标准HTTP) |
| 数据能力 | 二进制+文本 | 仅文本 |
| 断线恢复 | 手动实现 | 自动重连+消息追踪 |
| 适用场景 | 强交互应用 | 单向数据广播 |
📌 终极建议: 需要双向交互 → WebSocket 只需服务器推送+简单实现 → SSE 兼容旧系统 → SSE + Polyfill
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)