本文目录导读:

SSE (Server-Sent Events) 是一种允许服务器主动向客户端推送数据的技术,与 WebSocket 不同,SSE 是单向的(服务器到客户端),且基于 HTTP 协议。
以下是 SSE 的核心机制、实现示例及适用场景:
SSE 的核心特点
- 单向通信:数据只能从服务器流向客户端。
- 基于 HTTP:使用标准的 HTTP 协议,无需复杂的握手(如 WebSocket)。
- 自动重连:如果连接断开,浏览器会自动尝试重新连接(默认重试间隔 3 秒)。
- 文本传输:只能发送文本数据(UTF-8 编码),如果需要发送二进制数据,需要先编码为 Base64 或其他文本格式。
- 简单易用:客户端使用
EventSourceAPI,服务端返回text/event-stream格式的响应。
SSE 的工作原理
- 客户端请求:浏览器发起一个 GET 请求,并声明
Accept: text/event-stream。 - 服务端响应:服务端设置响应头
Content-Type: text/event-stream,并保持连接打开(不关闭)。 - 数据推送:服务端定期或不定期地向客户端发送格式化的文本消息。
- 客户端接收:浏览器通过
EventSource对象监听message或自定义事件。
完整实现示例
客户端(HTML + JavaScript)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">SSE 示例</title>
</head>
<body>
<h1>服务端推送消息</h1>
<div id="messages"></div>
<script>
// 创建 EventSource 对象,连接到服务端 SSE 端点
// 注意:如果跨域,需要设置 withCredentials: true 并服务端允许
const eventSource = new EventSource('/events');
// 监听默认的 message 事件(没有指定事件名称的消息)
eventSource.onmessage = function(event) {
const messagesDiv = document.getElementById('messages');
const newMessage = document.createElement('p');
newMessage.textContent = `收到消息: ${event.data}`;
messagesDiv.appendChild(newMessage);
};
// 监听自定义事件,"customEvent"
eventSource.addEventListener('customEvent', function(event) {
console.log('自定义事件:', event.data);
});
// 监听连接打开
eventSource.onopen = function() {
console.log('SSE 连接已建立');
};
// 监听错误(包括连接断开)
eventSource.onerror = function() {
console.error('SSE 连接出错');
// EventSource 会自动重连
};
// 关闭连接(例如页面离开时的清理)
// window.onbeforeunload = function() {
// eventSource.close();
// };
</script>
</body>
</html>
服务端(Node.js + Express 示例)
const express = require('express');
const app = express();
const PORT = 3000;
app.get('/events', (req, res) => {
// 设置 SSE 必需的响应头
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*' // 允许跨域
});
// 发送初始连接成功消息
res.write('data: 已连接\n\n');
// 每 2 秒发送一条消息
const intervalId = setInterval(() => {
const data = new Date().toLocaleTimeString();
res.write(`data: ${data}\n\n`);
// res.flushHeaders(); // 如果需要立即刷新缓冲区(某些框架需要)
}, 2000);
// 当客户端断开连接时,清理定时器
req.on('close', () => {
clearInterval(intervalId);
console.log('客户端断开连接');
res.end();
});
});
app.listen(PORT, () => {
console.log(`SSE 服务运行在 http://localhost:${PORT}`);
});
SSE 消息格式标准
服务端发送的消息行必须以 text/event-stream 格式,每条消息由多个字段组成:
field: value\n
常见字段:
data(必须,可以有多行)。event:事件名称(可选,客户端addEventListener监听)。id:消息 ID(可选,客户端自动设置Last-Event-ID以实现断线重连)。retry:重连时间(毫秒,可选)。
消息之间用两个换行符 \n\n 分隔。
示例:
event: userLogin
id: 12345
data: {"username": "张三", "time": "14:30:00"}
SSE 的优缺点
| 优点 | 缺点 |
|---|---|
简单易用:客户端只需 EventSource API。 |
单向通信:只能服务端推送,客户端无法发送数据(需结合 AJAX)。 |
| 自动重连:内置断线重连机制。 | 连接数限制:浏览器限制每个域名最多 6-8 个 SSE 连接。 |
| HTTP 兼容:走标准 HTTP 端口 80/443,防火墙友好。 | 文本传输:不支持二进制数据(除非编码)。 |
| 实时性较好:延迟一般在 1-3 秒内。 | 资源消耗:服务端需要保持大量长连接(可以使用 HTTP/2 提升效率)。 |
SSE vs WebSocket 对比
| 特性 | SSE | WebSocket |
|---|---|---|
| 通信方向 | 单向(服务端 → 客户端) | 双向(全双工) |
| 协议 | HTTP | WebSocket(非 HTTP) |
| 复杂性 | 简单 | 较复杂 |
| 自动重连 | 内置 | 需手动实现 |
| 二进制数据 | 需编码 | 原生支持 |
| 浏览器支持 | 良好(除 IE) | 广泛 |
| 应用场景 | 实时通知、日志流、股票价格 | 聊天、游戏、协同编辑 |
典型应用场景
- 实时通知系统:新订单提醒、系统告警。
- 股票/加密货币价格更新:低延迟推送行情。
- 日志流:持续推送服务器日志到前端。
- 社交媒体时间线:新帖子、新消息推送。
- 进度更新:文件上传/下载进度、任务执行状态。
注意事项
- 跨域问题:如果服务端和客户端不同域,需在服务端设置
Access-Control-Allow-Origin。 - 负载均衡:SSE 是长连接,负载均衡器需要配置
sticky session(会话保持),或使用 Redis 等中间件共享状态。 - 资源释放:服务端务必监听
req.on('close')事件,清理定时器和内存。 - 浏览器兼容性:IE 不支持,推荐使用 EventSource Polyfill 或降级方案(如轮询)。
高级用法:使用 EventID 实现断线重连
// 服务端发送带 ID 的消息
res.write(`id: ${Date.now()}\ndata: 消息内容\n\n`);
// 客户端自动携带 Last-Event-ID 重连
// 浏览器内部自动处理,无需额外代码
如果需要在重连时从最后一条消息开始,服务端可以读取请求头 Last-Event-ID:
const lastId = req.headers['last-event-id']; // 从 lastId 之后继续推送
SSE 是实现服务端单向推送最简单、最轻量的方案,如果你的需求只是服务端主动推送数据给客户端,且不需要客户端频繁发送数据回服务端(比如实时通知、新闻推送、系统状态更新),SSE 是比 WebSocket 更合适的选择。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播