SSE:Server-Sent Events(事件流)
SSE是一种在网页开发中使用的,基于HTTP长连接技术,允许服务器向客户端浏览器实时推送更新。
SSE的特性
- SSE只用来传送
文本,二进制数据需要转码后传送。 - SSE默认支持断线重送。
- 只能是
单向数据流,只能由服务器向客户端推送数据。
服务器的配置
- Content-Type:text/event-stream
- Cache-Control:no-cache
- Connection:keep-alive
sse(服务器推送事件)是一种用于在浏览器和服务器之间实现实时、单向通信的Web技术。它允许服务器向客户端推送数据,而无需要客户端发起请求。SSE建立一种持久的持续,通过这个连接,服务器可以随时向客户端发送更新的数据。这种实时数据的方式很适用于需要实时更新数据的应用,如聊天应用、股票行情、实时监控。
sse的原理
- 客户端通过创建一个EventSource对象与服务器建立连接。
- 服务器通过发送特定格式的事件流,如message事件,将数据推送给客户端。
- 客户端通过监听EventSource对象的事件,如message事件,来接收服务器发送的数据。
- 服务器可以根据需要发送不同的事件,如message事件,open事件,error事件。
sse建立连接的过程
- 客户端启动一个SSE连接:客户端使用
EventSource接口创建一个到服务器的连接。 - HTTP请求:客户端向服务器发送一个GET请求,并在请求头中加入
Accpet:text/event-stream表明这是一个SSE连接请求。 - 服务器响应:服务器处理这个请求后,保持该连接打开,并设置响应头
Content-Type:text/event-stream,告诉客户端后续的内容将是事件流。 - 发送消息:服务器周期性地发送格式化的消息数据给客户端,每条消息都是纯文本,以
data:开发,后面是消息内容,并以连续两个换行符\n\n结束。
本地模拟服务器代码:
const express = require("express");
const fs = require("fs");
const { clearInterval } = require("timers");
const app = express();
app.get("/api/sse", (req, res) => {
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Access-Control-Allow-Origin": "*",
});
const data = fs.readFileSync("./index.txt", "utf8");
const arr = data.split("");
let current = 0;
let timer = setInterval(() => {
if (current >= arr.length) {
clearInterval(timer);
} else {
res.write(`id:${current}\n`);
res.write("event:lol\n");
res.write(`data:${arr[current++]}\n\n`);
}
}, 300);
});
app.listen(3000, () => {
console.log("server is running");
});
本地客户端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="data"></div>
<script src="./sse.js"></script>
</body>
</html>
document.addEventListener("keydown", (e) => {
if (e.key == "Enter") {
const sse = new EventSource("http://localhost:3000/api/sse");
sse.addEventListener("open", (e) => {
console.log(e.target);
});
sse.addEventListener("lol", (e) => {
document.getElementById("data").innerHTML += e.data;
});
sse.onerror = (e) => {
console.log(e);
};
}
});