当前位置: 首页 > news >正文

[Node.js] Server-Sent Events

远程通信方式

通信方式:

  1. Stdio: 推荐,高效、简洁、本地
  2. Streamable HTTP: 远程

前置知识

SSE 全称 Server-Sent Events,中文是“服务器发送事件”。是一种基于 HTTP 的单向通信协议,由浏览器发起连接,服务器可以持续不断地向客户端推送数据

你可以把它想象成:“浏览器打开一个通道,然后服务器不断地往里面发消息。”

SSE 特点

  1. 协议:基于 HTTP(长连接)
  2. 方向:单向:服务器 -> 客户端
  3. 格式:文本流,内容类型为 text/event-stream
  4. 浏览器支持:所有现代浏览器都支持(IE 除外)
  5. 应用场景:单方面需要推送的时候。实时通知、消息流、状态更新、股票/天气数据等

消息格式

SSE 协议规定,服务器以 text/event-stream 格式不断推送消息,每条消息格式如下:

event: 事件名   # 可选,默认是 message 事件
id: 唯一ID     # 可选
retry: 3000   # 客户端断线重连间隔,单位毫秒,可选
data: 内容     # 必需,可以多行

每条消息用空行 \n\n 作为结尾。

事件类型

如果服务器发送的数据中没有指定事件类型,浏览器端会将其作为默认事件类型 message 来处理:

data: 这是默认消息(data 代表要发送的消息)

客户端监听方式:

eventSource.addEventListener("message", (e) => {console.log("默认事件:", e.data);
});

可以自定义事件名:使用 event: 字段

event: update(事件名)
data: 新的更新内容

客户端监听方式:

eventSource.addEventListener("update", (e) => {console.log("收到 update 事件:", e.data);
});

课堂练习

SSE 服务器推送信息示例

import express from "express";
import { watch } from "chokidar";
import { join } from "path";
import { fileURLToPath } from "url";
import { dirname } from "path";const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);const app = express();const clients = new Set(); // 存储所有的客户端连接app.use(express.static(join(__dirname, "public")));app.get("/mcp", (req, res) => {res.setHeader("Content-Type", "text/event-stream");res.setHeader("Cache-Control", "no-cache");res.setHeader("Connection", "keep-alive");// 假设现在客户端连接过来,那么这里就给客户端推送一个消息res.write("event:connected\n"); // 事件名res.write("data:你已经连接上SSE服务器\n\n"); // 推送的数据clients.add(res);// 在客户端断开连接的时候,会触发 close 事件req.on("close", () => {clients.delete(res);});
});// 监听目录
const watcher = watch(join(__dirname, "watched"), {persistent: true,ignoreInitial: true,
});// 需要在目录发生变化的时候,通知所有的客户端
watcher.on("all", (event, path) => {// 将监听到的变化的信息,通知所有的客户端// 1. 组装要发送给客户端的信息const payload = JSON.stringify({event, // 当前资源发生变化 1. 新增 add  2. 删除 unlink  3. 修改 changepath, // 文件的路径time: new Date().toLocaleString(),});// 2. 通知所有的客户端for (const client of clients) {client.write(`event: resource_changed\n`);client.write(`data: ${payload}\n\n`);}console.log(`【发生了变更】${event} -> ${path}`);
});app.listen(3000, () => {console.log(`服务器已启动, 监听3000端口`);
});
http://www.hskmm.com/?act=detail&tid=25241

相关文章:

  • day1 Gitlab Runner 学习
  • Software Foundations Vol.I : 使用结构化的数据(Lists)
  • Software Foundations Vol.I : 归纳证明(Induction)
  • Software Foundations Vol.I : Coq函数式编程(Basics)
  • Python 在自然语言处理中的应用与发展
  • Python 在网络爬虫与数据采集中的应用
  • 15_spring_data_neo4j简单教程
  • CF2152G Query Jungle(线段树,重链剖分,*)
  • 代码随想录算法训练营第九天 | leetcode 151 卡特55
  • [题解] 分竹子
  • 分数规划
  • CSS - transition 粗浅记忆
  • 【MC】LittleTiles模组结构数据解析和版本迁移方案
  • 容器魔方导致盒子满了
  • 课程学习笔记——[大一秋]遗传学
  • P3067 [USACO12OPEN] Balanced Cow Subsets G
  • Vivado 2025 界面中文设置
  • 词汇学习——专业词汇
  • P4556 [Vani有约会] 雨天的尾巴 [模板] 线段树合并
  • P4550 收集邮票
  • P8110 [Cnoi2021] 矩阵
  • P9751 [CSP-J 2023] 旅游巴士
  • P9234 [蓝桥杯 2023 省 A] 买瓜
  • P1044 [NOIP 2003 普及组] 栈
  • P1080 [NOIP 2012 提高组] 国王游戏
  • 音响没声音
  • P1654 OSU!
  • DynamoDB十年演进:云原生数据库的技术革新
  • 完整教程:MySQL全量、增量备份与恢复
  • 10/5