WebSocket 和 SSE(Server-Sent Events)都是用于 服务器向客户端实时推送数据 的技术,但核心设计、适用场景和特性有显著区别。以下从多个维度详细对比,帮你快速理清二者差异:
一、核心定义与通信模式
| 特性 | WebSocket | SSE(Server-Sent Events) |
|---|
| 通信方向 | 全双工(双向通信):客户端 ↔ 服务器均可主动发送数据 | 半双工(单向通信):仅服务器 → 客户端推送,客户端仍需通过 HTTP (如 POST)主动发送数据 |
| 底层协议 | 独立的 WebSocket 协议(ws:///wss://),基于 TCP 握手后升级 | 基于 HTTP/HTTPS 协议(复用现有 HTTP 连接) |
| 连接本质 | 单一 TCP 长连接,协议升级后与 HTTP 解耦 | 基于 HTTP 长轮询的优化(保持连接不中断,服务器持续发送数据) |
| 数据格式 | 二进制帧 + 文本帧(支持任意格式:JSON、Protobuf、文件等) | 仅文本格式(UTF-8),默认按行分隔的 text/event-stream 格式(包含 data/event/id 等字段) |
二、关键技术细节对比
1. 连接建立与关闭
- WebSocket:
- 客户端发送 HTTP 握手请求(带
Upgrade: websocket 和 Sec-WebSocket-Key 头); - 服务器响应
101 Switching Protocols,完成协议升级; - 连接建立后,双方通过帧格式(带 opcode、掩码、长度)通信;
- 关闭需发送
Close 帧,双方确认后断开 TCP 连接。
- SSE:
- 客户端发送普通 HTTP GET 请求(头
Accept: text/event-stream); - 服务器响应
200 OK,头 Content-Type: text/event-stream + Cache-Control: no-cache,保持连接不关闭; - 客户端断开时直接关闭 HTTP 连接(服务器通过 TCP 断连感知);
- 支持自动重连(客户端内置
retry 机制,服务器可指定重连间隔)。
2. 数据传输效率
- WebSocket:
- 升级后无 HTTP 头开销(仅帧头约 2-14 字节),二进制传输效率极高;
- 支持分片传输大文件、二进制流(如视频、语音)。
- SSE:
- 基于 HTTP 长连接,每个数据块需带 SSE 格式头(如
data: ),文本传输有额外开销; - 不支持二进制数据(需手动 Base64 编码,进一步降低效率)。
3. 兼容性与穿透性
- WebSocket:
- 浏览器支持:IE10+、所有现代浏览器(兼容性良好);
- 穿透性:需服务器支持 WebSocket 协议升级,部分老旧代理/防火墙可能拦截(需通过
wss:// 或反向代理转发规避)。
- SSE:
- 浏览器支持:IE 不支持(需 polyfill),现代浏览器均支持;
- 穿透性:基于 HTTP,无协议升级,可直接通过现有 HTTP 代理/防火墙(兼容性更好,部署成本低)。
4. 功能特性
| 功能点 | WebSocket | SSE |
|---|
| 断线重连 | 需手动实现(监听 onclose 事件) | 客户端内置自动重连(retry 字段控制) |
| 消息确认(ACK) | 需自定义协议(如添加 ACK 帧) | 需客户端通过 HTTP 单独发送确认 |
| 自定义事件类型 | 需封装在消息体中(如 JSON 字段) | 原生支持(通过 event: 事件名 定义) |
| 消息ID与重连续传 | 需自定义 | 原生支持(id: 消息ID,重连时带 Last-Event-ID) |
| 跨域支持 | 需服务器配置 Access-Control-Allow-Origin | 同 HTTP 跨域规则(天然支持) |
三、适用场景对比
优先选 WebSocket 的场景
- 需 双向实时通信:如聊天软件(微信网页版)、实时协作工具(腾讯文档)、多人游戏;
- 需 高效传输二进制数据:如实时视频流、文件分片上传、物联网设备数据(传感器二进制流);
- 高并发、低延迟需求:如股票行情推送、直播弹幕(需服务器主动推+客户端快速反馈)。
优先选 SSE 的场景
- 仅需 服务器单向推送:如新闻实时更新、体育比分推送、日志实时监控(客户端无需向服务器发数据);
- 追求 简单部署:不想改动服务器协议(仅需支持 HTTP),无需处理 WebSocket 升级、帧解析;
- 兼容性要求(需兼容老旧 HTTP 代理):SSE 基于 HTTP,穿透性比 WebSocket 更好;
- 轻量需求(无需复杂功能):如简单的通知推送(无需二进制、无需双向通信)。
四、代码示例(简单对比)
1. WebSocket 示例(客户端 + 服务器)
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => ws.send('客户端消息');
ws.onmessage = (e) => console.log('收到服务器消息:', e.data);
ws.onclose = () => console.log('连接关闭');
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
ws.send('服务器欢迎消息');
ws.on('message', (data) => console.log('收到客户端消息:', data));
});
2. SSE 示例(客户端 + 服务器)
const sse = new EventSource('http://localhost:8080/sse');
sse.onmessage = (e) => console.log('收到普通消息:', e.data);
sse.addEventListener('news', (e) => console.log('收到新闻事件:', e.data));
sse.onerror = () => console.log('连接错误(将自动重连)');
const express = require('express');
const app = express();
app.get('/sse', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Access-Control-Allow-Origin', '*');
res.write('data: 服务器推送的普通消息
');
res.write('event: news
');
res.write('data: 最新新闻:xxx
');
setInterval(() => res.write(`data: 实时更新 ${Date.now()}
`), 1000);
});
app.listen(8080);
五、总结表格
| 对比维度 | WebSocket | SSE |
|---|
| 通信方向 | 全双工(双向) | 半双工(单向:服务器→客户端) |
| 协议基础 | 独立 WebSocket 协议(ws:///wss://) | HTTP/HTTPS 协议 |
| 数据格式 | 二进制 + 文本(任意格式) | 仅文本(text/event-stream) |
| 传输效率 | 高(无 HTTP 头开销) | 中(有 SSE 格式开销,不支持二进制) |
| 断线重连 | 需手动实现 | 原生支持 |
| 部署复杂度 | 中(需服务器支持协议升级) | 低(复用 HTTP 服务器) |
| 浏览器兼容性 | IE10+,现代浏览器全支持 | IE 不支持,现代浏览器全支持 |
| 典型场景 | 聊天、协作、游戏、二进制流推送 | 新闻、日志、比分、单向通知推送 |
核心决策建议
- 如果需要 客户端向服务器主动发消息(双向通信),直接选 WebSocket;
- 如果仅需 服务器推数据(单向),且想简化部署、兼容老旧网络,选 SSE;
- 如果涉及 二进制数据传输(如视频、文件),只能选 WebSocket。