SSE服务器到客户端单向推送

目录:

一、使用场景以及与websocket的区别

SSE:

websocket:

选型建议:

  • 只要服务端推送(行情、通知、日志)→ 优先 SSE,简单、纯 HTTP、天然兼容 HTTP/2 多路复用
  • 需要双向频繁通信(聊天、协同、游戏)→ WebSocket
  • 不要为了"实时"硬上 WebSocket,SSE 能搞定的就 SSE,运维成本低一档

二、SSE(Server-Sent Events)数据推送机制

1. 推送原理

  • 服务器→客户端单向推送:SSE基于HTTP协议,通过长连接实现服务器主动向客户端推送数据。
  • 数据格式:服务器发送的数据必须符合特定格式:data: 内容\n\n(data:是默认事件名,可通过event: 自定义事件名指定)。
  • 持久连接:服务器保持连接打开,客户端通过EventSource对象接收数据。

2. 前端接收方式

javascript 复制代码
// 1. 创建EventSource实例(连接服务器)
const eventSource = new EventSource('/sse/events');

// 2. 监听默认的message事件(接收服务器推送的数据)
eventSource.onmessage = function(event) {
    console.log('收到数据:', event.data); // 数据被推送到这里
    // 可以更新DOM、触发业务逻辑等
};

// 3. 监听自定义事件(如服务器发送的"update"事件)
eventSource.addEventListener('update', function(event) {
    console.log('收到更新事件:', event.data);
});

3. 数据流向

java 复制代码
服务器 → HTTP响应流 → 浏览器EventSource解析 → onmessage事件 → 前端处理

三、实际应用示例

1.SSE后端推送数据

javascript 复制代码
// Node.js后端(Express)
app.get('/sse/events', (req, res) => {
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    
    // 模拟实时数据推送(每秒发送一次)
    setInterval(() => {
        res.write(`data: ${new Date().toISOString()}\n\n`);
    }, 1000);
});

四、注意事项

📌 EventSource构造函数参数说明

1.参数含义

  • URL:服务器端提供SSE事件流的接口地址
  • 可以是相对路径(如/sse/events)或绝对路径(如http://localhost:3000/sse/events)
  • 必须是HTTP或HTTPS协议的URL

2.参数要求

javascript 复制代码
const eventSource = new EventSource(url, [options]);
  • url:必需,服务器端SSE接口地址
  • options:可选,配置对象,常用属性:
javascript 复制代码
  {
    withCredentials: true  // 是否携带跨域凭据(如cookies)
  }

3.示例

javascript 复制代码
// 相对路径(同源请求)
const eventSource = new EventSource('/sse/events');

// 绝对路径(跨域请求)
const eventSource = new EventSource('https://api.example.com/sse/events', {
    withCredentials: true  // 携带跨域凭据
});

五、服务器端接口要求

1.响应头设置

服务器端必须返回特定的响应头:

java 复制代码
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

2.数据格式

服务器发送的数据必须符合SSE格式:

java 复制代码
data: 事件数据\n\n  // 基本格式
id: 消息ID\n      // 可选,用于重连定位
event: 事件名\n   // 可选,自定义事件名
retry: 5000\n    // 可选,重连间隔(毫秒)

3.示例响应

java 复制代码
data: {"message": "Hello SSE!"}\n\n
id: 12345\n
event: update\n
data: {"status": "online"}\n\n

4.CORS配置

如果接口是跨域的,服务器端需要设置CORS头:

java 复制代码
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

5.前后端代码示例

前端代码:

javascript 复制代码
const eventSource = new EventSource('/sse/events');

eventSource.onmessage = function(event) {
    console.log('收到数据:', event.data);
};

eventSource.onerror = function(error) {
    console.error('连接错误:', error);
    if (eventSource.readyState === EventSource.CLOSED) {
        // 可以尝试重新连接
        setTimeout(() => {
            eventSource = new EventSource('/sse/events');
        }, 5000);
    }
};

后端代码(node.js):

javascript 复制代码
app.get('/sse/events', (req, res) => {
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    
    // 定时推送数据
    setInterval(() => {
        res.write(`data: ${JSON.stringify({time: new Date().toISOString()})}\n\n`);
    }, 1000);
});