HTML5 服务器发送事件(Server-Sent Events)
HTML5 服务器发送事件 (Server-Sent Events, SSE) 是一种用于在客户端和服务器之间通过单向连接进行实时数据传输的技术。通过 SSE,服务器能够向浏览器发送推送消息,而无需客户端不断地轮询服务器。SSE 使得 Web 应用能够接收来自服务器的实时数据更新,并且这种数据流是单向的(从服务器到客户端)。
SSE 的工作原理:
- 单向通信: SSE 通过 HTTP 协议实现从服务器到客户端的单向通信。
- 长连接: 客户端与服务器建立持久的 HTTP 连接,一旦连接建立,服务器可以随时通过这个连接向客户端推送消息。
- 文本格式: SSE 使用文本格式(通常是 UTF-8 编码),并通过事件流传输数据。
为什么选择 SSE:
- 简洁易用: 与 WebSocket 相比,SSE 在实现和使用上更加简单,适合只需要从服务器推送数据到客户端的场景。
- 内建支持: SSE 是基于 HTTP 的标准,浏览器本身就有对其的支持,不需要额外的库或协议。
- 适合单向流: SSE 非常适合于实时新闻、股票行情、通知推送等只需要服务器向客户端传递数据的应用场景。
创建 SSE 的基本步骤:
- 在服务器端创建 SSE 连接:
服务器需要向客户端发送Content-Type: text/event-stream头部,以告知浏览器该连接为 SSE 流。服务器将持续通过该连接向客户端发送事件。 - 在客户端使用
EventSource接收 SSE:
客户端通过EventSourceAPI 来接收来自服务器的事件流。
服务器端代码示例:
服务器端的处理方式取决于你使用的服务器技术。下面是一个使用 Node.js 创建 SSE 服务器的简单示例:
// Node.js 服务器端示例
const http = require('http');
http.createServer((req, res) => {
// 检查是否是 SSE 请求
if (req.url === '/events') {
res.writeHead(200, {
'Content-Type': 'text/event-stream', // 指定 SSE 格式
'Cache-Control': 'no-cache', // 禁止缓存
'Connection': 'keep-alive', // 保持连接
});
// 每 1 秒发送一次消息
setInterval(() => {
res.write('data: ' + JSON.stringify({ message: 'Hello from server' }) + '\n\n');
}, 1000);
} else {
// 对于其他请求,返回 404
res.writeHead(404);
res.end();
}
}).listen(3000, () => {
console.log('Server is listening on http://localhost:3000');
});
客户端代码示例:
客户端使用 EventSource 对象来接收 SSE 消息。EventSource 自动处理与服务器的连接和事件接收。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Server-Sent Events Example</title>
</head>
<body>
<h1>Real-time messages from server</h1>
<div id="messages"></div>
<script>
// 创建 EventSource 实例,连接到服务器端的 /events 路径
const eventSource = new EventSource('/events');
// 监听服务器发送的消息
eventSource.onmessage = function(event) {
const messageDiv = document.getElementById('messages');
const data = JSON.parse(event.data); // 解析服务器发送的 JSON 数据
messageDiv.innerHTML += `<p>${data.message}</p>`;
};
// 错误处理
eventSource.onerror = function() {
console.error('Error occurred while receiving SSE.');
eventSource.close();
};
</script>
</body>
</html>
解释:
EventSource: 这个对象用于在客户端与服务器之间建立一个持久的连接,并接收服务器通过该连接推送的事件数据。onmessage: 用于处理来自服务器的消息。当服务器推送新的事件时,onmessage事件会被触发,并将事件数据传递给客户端。onerror: 用于处理连接错误。如果连接丢失或发生错误,onerror会被触发,通常可以在这里进行一些重试逻辑或资源清理。
SSE 数据格式:
SSE 消息是文本格式,并且每个事件都由以下部分组成:
- 事件类型: 可选,表示事件的类型。
- 数据: 事件的主要数据,通常是字符串。
- ID: 可选,表示事件的唯一 ID。
- 重试: 可选,表示客户端重新连接的重试间隔(单位为毫秒)。
一个完整的 SSE 消息如下:
id: 123
event: customEvent
data: {"message": "Hello, world!"}
retry: 10000
服务器端事件的类型:
- 默认事件: 如果没有指定事件类型,浏览器会触发
onmessage事件来接收数据。 - 自定义事件: 通过
event字段指定自定义事件类型。浏览器会触发相应的on[eventType]事件处理器。
// 在服务器端发送自定义事件
res.write('event: customEvent\n');
res.write('data: {"message": "Custom event triggered"}\n\n');
客户端接收自定义事件:
eventSource.addEventListener('customEvent', function(event) {
const data = JSON.parse(event.data);
console.log('Custom event received:', data);
});
SSE 优缺点:
优点:
- 简单易用: SSE 基于 HTTP 和标准的浏览器 API,无需复杂的库或协议。
- 实时更新: 可以实现从服务器到客户端的实时数据推送。
- 自动重连: 如果连接丢失,SSE 会自动重连,不需要手动处理。
缺点:
- 单向通信: SSE 仅支持从服务器到客户端的单向数据流,不适用于需要双向通信的场景(比如聊天应用)。
- 浏览器支持: 大多数现代浏览器支持 SSE,但一些较老的浏览器(如 Internet Explorer)不支持。需要考虑兼容性问题。
- 有限的事件量: 如果需要处理大量实时数据(比如高频的实时消息),SSE 可能会有性能瓶颈。相比之下,WebSocket 提供了更高效的双向通信。
总结:
HTML5 服务器发送事件(SSE)是一个简单而强大的技术,适用于从服务器到客户端推送实时数据的场景。它相比 WebSocket 更为简单,适用于单向消息流的应用。通过 SSE,Web 应用能够实现实时通知、数据更新和其他推送功能,同时减少了传统轮询的负担。