html服务器发送事件怎么用?html服务器发送事件实例
- 云服务器
- 2026-07-12
- 5
HTML 服务器发送事件(Server-Sent Events,简称 SSE)是一种允许网页从服务器接收自动更新的技术,与 WebSocket 不同,SSE 是单向通信协议,仅用于服务器向客户端推送数据,它基于 HTTP 协议,使用纯文本格式传输数据,因此实现简单且兼容性好,特别适用于新闻推送、股票行情、社交动态通知等场景。
核心概念与工作原理
SSE 的核心在于建立一条持久的 HTTP 连接,客户端通过 EventSource 对象发起请求,服务器则保持该连接打开,并持续发送数据流,一旦数据到达,客户端会自动触发相应的事件处理程序。
客户端实现:EventSource API
在 JavaScript 中,使用 EventSource 构造函数来创建与服务器的连接,该对象会自动处理重连逻辑,如果连接断开,它会尝试重新连接。
// 创建 EventSource 实例,指向服务器端点 const eventSource = new EventSource('/api/sse'); // 监听默认消息事件 eventSource.onmessage = function(event) { console.log('收到数据:', event.data); // 更新 UI 或处理数据 }; // 监听自定义事件 eventSource.addEventListener('news_update', function(event) { console.log('新闻更新:', event.data); }); // 监听连接打开事件 eventSource.onopen = function() { console.log('SSE 连接已建立'); }; // 监听错误事件 eventSource.onerror = function(error) { console.error('SSE 连接错误:', error); // 注意:EventSource 会自动尝试重连,除非服务器返回 401 或 403 };
服务器端实现:响应格式
服务器必须设置正确的 HTTP 响应头,并遵循特定的数据格式,关键响应头包括:

- Content-Type: text/event-stream:告诉浏览器这是 SSE 数据流。
- Cache-Control: no-cache:防止浏览器缓存响应。
- Connection: keep-alive:保持连接打开。
数据格式规范:
SSE 数据由字段组成,每个字段以 key: value 的形式出现,并以换行符 n 整个消息块以两个换行符 nn 结束。
| 字段名 | 说明 | 示例 |
|---|---|---|
| data | 必需字段,承载实际数据内容,如果数据有多行,每行后都需加 n。 | data: Hello Worldn |
| event | 可选字段,定义事件类型,默认为 message。 | event: news_updaten |
| id | 可选字段,设置消息 ID,用于重连时的 Last-Event-ID 机制。 | id: 12345n |
| retry | 可选字段,指定客户端重连前的等待时间(毫秒)。 | retry: 3000n |
服务器端代码示例(Node.js + Express):
SSE 与 WebSocket 的对比
选择 SSE 还是 WebSocket 取决于应用的具体需求,以下是两者的主要区别:
| 特性 | Server-Sent Events (SSE) | WebSocket |
|---|---|---|
| 通信方向 | 单向(服务器 -> 客户端) | 双向(客户端 <-> 服务器) |
| 协议 | 基于 HTTP/HTTPS | 独立的 WebSocket 协议(ws:// 或 wss://) |
| 数据格式 | 纯文本(UTF-8) | 二进制或文本 |
| 重连机制 | 内置自动重连 | 需手动实现重连逻辑 |
| 浏览器支持 | 现代浏览器广泛支持(IE 不支持) | 现代浏览器广泛支持(IE 10+ 支持) |
| 适用场景 | 新闻流、股票行情、状态更新 | 聊天应用、在线游戏、实时协作 |
高级特性:Last-Event-ID 与重连
SSE 的一个重要特性是支持断线重连时的状态恢复,如果服务器在发送消息时指定了 id 字段,客户端会保存最后一个接收到的 ID,当连接断开并尝试重连时,客户端会在 HTTP 请求头中发送 Last-Event-ID,服务器可以根据此 ID 决定从哪条消息开始继续推送,避免数据丢失或重复处理。
服务器端处理 Last-Event-ID 示例:
app.get('/api/sse', (req, res) => { // 获取客户端发送的 Last-Event-ID const lastEventId = req.headers['last-event-id']; // 根据 lastEventId 查询数据库或内存,找到最后一条消息的 ID // lastEventId 为 '100',服务器应从 ID 为 101 的消息开始推送 const startFromId = lastEventId ? parseInt(lastEventId) + 1 : 1; res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); // 推送历史消息(可选) for (let i = startFromId; i <= 105; i++) { res.write(`id: ${i}ndata: Historical message ${i}nn`); } // 继续实时推送... });
优缺点分析
优点:

- 实现简单:基于标准 HTTP,无需额外的协议栈,防火墙和代理服务器通常不会拦截。
- 自动重连:EventSource 内置了指数退避重连机制,减少了开发负担。
- 轻量级:相比 WebSocket,SSE 的协议开销更小,适合低频更新场景。
- 易于调试:纯文本格式,可以直接在浏览器开发者工具中查看。
缺点:
- 单向通信:无法从客户端向服务器发送数据,如需双向通信需结合 HTTP 请求。
- 浏览器兼容性:Internet Explorer 完全不支持 SSE,需考虑降级方案。
- 连接限制:浏览器对同一域名的并发 HTTP 连接数有限制(通常为 6 个),大量 SSE 连接可能耗尽连接池。
- 不适合高频数据:对于每秒数千次更新的高频场景,WebSocket 的性能更优。
最佳实践建议
- 使用 HTTPS:虽然 SSE 可以在 HTTP 上工作,但出于安全和跨域考虑,建议在 HTTPS 环境下使用。
- 设置合理的重试时间:通过 retry 字段控制重连间隔,避免服务器过载。
- 监控连接状态:在 onerror 中记录日志,以便排查连接问题。
- 清理资源:在客户端不再需要 SSE 连接时,调用 eventSource.close() 关闭连接,释放服务器资源。
- 考虑降级方案:对于不支持 SSE 的浏览器,可回退到长轮询(Long Polling)或轮询(Polling)。
相关问题与解答
问题 1:SSE 是否支持二进制数据传输?
解答:
不支持,SSE 协议规定数据必须以 UTF-8 编码的纯文本格式传输,如果需要在 SSE 中传输二进制数据,必须先将二进制数据编码为文本格式,例如使用 Base64 编码,客户端收到数据后,再将其解码回二进制格式,这种方式会增加数据体积和编解码开销,因此对于大量二进制数据传输,建议使用 WebSocket。
问题 2:如何在 SSE 中实现客户端向服务器发送数据?
解答:
SSE 本身是单向协议,不支持从客户端向服务器发送数据,如果需要实现双向通信,通常采用以下两种方案:
- 结合 HTTP 请求:客户端通过标准的 fetch 或 XMLHttpRequest 发送 POST/PUT 请求来向服务器发送数据,同时保持 SSE 连接用于接收服务器推送,这是最常见的做法。
- 使用 WebSocket:如果应用需要频繁的双向通信,直接改用 WebSocket 是更合适的选择,因为它原生支持全双工通信。
