文章目录
单工通信是一种
单向
的通信方式,其中信息只能从发送端传输到接收端,而接收端不能向发送端发送任何信息
。在Web开发中,Server-Sent Events (SSE) 是一种实现单工通信的技术,允许服务器
将更新数据推送到客户端
1、SSE 流式传输
SSE是一种由HTML5引入的技术,用于在服务器和浏览器之间创建持久的单向连接。通过这种连接,
服务器可以不断地向浏览器推送数据
,而不需要客户端轮询
服务器以获取更新。SSE使用HTTP协议,并且在浏览器端使用EventSource对象
来接收服务器发送的事件。
chatgpt
的 问题回答, 就是用的这种方式
- 优点:
- 简单易用,使用标准HTTP协议。
- 在许多现代浏览器中都有良好的支持。
- 对于
实时更新
的应用,如新闻推送、股票行情、聊天系统、倒计时同步、实时天气等非常适用。
- 缺点:
单向通信
,客户端无法向服务器发送数据(适合使用WebSocket)。- 不适合传输大量数据或需要双向通信的应用。
2、后端代码
- 采用
express
起一个服务 - 用
cors
处理跨域问题 - 设置SSE 技术必要的响应头
在向前端传输数据的时候, res.write 里面的东西 如若有变量啥的,一定要转化成字符串
SSE 响应
主要由一系列以两个换行符分隔
的事件组成。每个事件可以包含以下字段:
data
:事件的数据。如果数据跨越多行,每行都应该以data:开始。- id:事件的唯一标识符。客户端可以使用这个ID来恢复事件流。
- event:自定义事件类型。客户端可以根据不同的事件类型来执行不同的操作。
- retry:建议的重新连接时间(毫秒)。如果连接中断,客户端将等待这段时间后尝试重新连接。
js
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
function formatDate() {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1; // getMonth() 返回 0-11,需要 +1
const day = now.getDate();
const hours = now.getHours();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
app.use(express.static("public"));
app.get("/events", function (req, res) {
// 必要的一些响应头配置
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
res.header("Access-Control-Allow-Origin", "*"); // 允许所有来源
let count = 1;
let intervalInstance = setInterval(() => {
if (count == 10) {
res.write(
`data:${JSON.stringify({
data: formatDate(),
count: count,
})}\n\n`
); // 发送一个特殊事件通知客户端关闭
res.end();
clearInterval(intervalInstance);
return;
}
res.write(
`data: ${JSON.stringify({
data: formatDate(),
count: count,
})}\n\n`
);
count++;
}, 2000);
});
app.listen(3000, () => {
console.log(`http://localhost:3000`);
});
3、前端代码
每次接收后端返回值结构如下
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
</head>
<body>
<h1>Server-SentEvents</h1>
<div id="container"></div>
<script>
const evtSource = new EventSource("http://127.0.0.1:3000/events");
const container = document.getElementById("container");
evtSource.onmessage = function (event) {
console.log(event, JSON.parse(event.data));
let data = JSON.parse(event.data)
if (data.count == 10) {
evtSource.close();
}
const pEl = document.createElement("p");
pEl.innerHTML = data.data + ' 次数' + data.count
container.appendChild(pEl);
};
</script>
</body>
</html>
##4、实际效果
5、SSE和WS 对比
WebSocket:是
全双工通信
特性/因素 | SSE | WS(WebSocket) |
---|---|---|
协议 | 基于HTTP,使用标准HTTP连接 | 单独的协议(ws:// 或 wss://),需要握手升级 |
通信方式 | 单向通信(服务器到客户端) | 全双工通信 |
数据格式 | 文本(UTF-8编码) | 文本或二进制 |
重连机制 | 浏览器自动重连 | 需要手动实现重连机制 |
实时性 | 高(适合频繁更新的场景) | 非常高(适合高度交互的实时应用) |
浏览器支持 | 良好(大多数现代浏览器支持) | 非常好(几乎所有现代浏览器支持) |
适用场景 | 实时通知、新闻feed、股票价格等需要从服务器推送到客户端的场景 | 在线游戏、聊天应用、实时交互应用 |
复杂性 | 较低,易于实现和维护 | 较高,需要处理连接的建立、维护和断开 |
兼容性和可用性 | 基于HTTP,更容易通过各种中间件和防火墙 | 可能需要配置服务器和网络设备以支持WebSocket |
服务器负载 | 适合较低频率的数据更新 | 适合高频率消息和高度交互的场景 |
6、chatgpt SSE的服务端返回的数据
这里他其实返回的是
unicode
编码的字符