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

【AI落地工程技术】-SSE协议

目录

SSE协议内容

SSE事件格式

使用示例

示例一

客户端(JavaScript)

服务器端(Node.js 示例)

示例二

前端(JavaScript)

后端(Java,使用Spring Boot和Servlet API)


SSE(Server-Sent Events)协议是一种用于服务器主动向客户端推送数据的技术,也称为“事件流”(Event Stream)。它基于HTTP协议,利用长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送。ChatGPT即采用的是SSE协议。

SSE协议内容

  1. 协议头
    • SSE协议返回的是事件流,需要指定内容类型。因此,在HTTP header里需要加上以下信息:
      • Content-Type: text/event-stream
      • Connection: keep-alive
      • Cache-Control: no-cache
  2. 协议内容
    • 协议内容放在HTTP返回的body里,每次返回一个Event信息。
    • 每个Event里可以包含以下5个属性(但并非所有属性都是必需的):
      • id:用于表示Event的序号,客户端通过序号实现断线重连功能。
      • event:表示自定义事件类型,客户端通过该字段区分不同消息。
      • data:表示返回的业务数据,如果数据很长可以分成多行返回。
      • retry:(可选)注释消息,表示重新连接的时间间隔(单位:毫秒)。
    • 每个属性值占用一行,每行的内容都是由属性名称+属性值组成+换行符,之间用冒号隔开(:)。
    • 两个消息之间用额外的换行符(\n\n)区分。

SSE事件格式

每个SSE事件都以文本形式发送,遵循以下格式:

  • 单行注释:以: 开头(例如 : 这是一条注释\n
  • 字段:由字段名、冒号、字段值以及一个换行符组成(例如 data: This is a message\n
  • 事件:通过event字段指定(例如 event: myevent\n
  • ID:通过id字段指定,用于在重新连接时帮助客户端确定错过的消息(例如 id: 123\n
  • 重试:通过retry字段指定在重新连接之前的延迟时间(单位:毫秒)(例如 retry: 2000\n
  • 消息结束:两个换行符(\n\n)表示一个事件的结束和下一个事件的开始

使用示例

示例一

客户端(JavaScript)

// 创建EventSource对象  
const eventSource = new EventSource('http://example.com/sse');  // 监听服务器发送的事件  
eventSource.onmessage = function(event) {  console.log('收到消息:', event.data);  
};  // 监听服务器关闭连接的事件  
eventSource.onclose = function() {  console.log('连接已关闭');  
};  // 监听服务器错误事件  
eventSource.onerror = function() {  console.log('连接出错');  
};


服务器端(Node.js 示例)

const http = require('http');  const server = http.createServer((req, res) => {  if (req.url === '/sse' && req.method === 'GET') {  // 设置响应头  res.writeHead(200, {  'Content-Type': 'text/event-stream',  'Connection': 'keep-alive',  'Cache-Control': 'no-cache'  });  // 模拟发送数据  let count = 0;  const interval = setInterval(() => {  const eventData = `data: 这是第 ${count++} 条消息\n\n`;  res.write(eventData);  // 假设在发送10条消息后关闭连接  if (count > 10) {  clearInterval(interval);  res.end();  }  }, 1000); // 每秒发送一次  }  
});  server.listen(8080, () => {  console.log('SSE 服务器已启动,监听 8080 端口');  
});
在上面的示例中,客户端使用EventSource对象创建一个与服务器端的SSE连接,并监听不同的事件。服务器端则创建一个HTTP服务器,并在接收到特定的GET请求时,通过长连接向客户端发送数据。这个示例模拟了一个简单的SSE服务器,每秒钟向客户端发送一条消息,并在发送了10条消息后关闭连接。

示例二

前端(JavaScript)

// 创建EventSource实例并连接到SSE服务  
var source = new EventSource('/server-sent-events-endpoint');  // 监听message事件(默认事件类型)  
source.onmessage = function(event) {  console.log('Received data:', event.data);  
};  // 监听自定义事件类型  
source.onmyevent = function(event) {  console.log('Received myevent:', event.data);  
};  // 监听连接打开事件  
source.onopen = function(event) {  console.log('Connection to server opened.');  
};  // 监听连接错误事件  
source.onerror = function(event) {  if (source.readyState === EventSource.CLOSED) {  // 连接已关闭,可以尝试重新连接  console.log('Connection to server was closed.');  }  
};

后端(Java,使用Spring Boot和Servlet API)

在Spring Boot应用中,你可以使用@RestController@GetMapping来创建一个SSE端点,但更常见的是使用ServletResponse直接发送SSE消息。

import javax.servlet.ServletException;  
import javax.servlet.annotation.WebServlet;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import java.io.IOException;  
import java.io.PrintWriter;  @WebServlet("/server-sent-events-endpoint")  
public class SseServlet extends HttpServlet {  @Override  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  resp.setContentType("text/event-stream");  resp.setCharacterEncoding("UTF-8");  PrintWriter out = resp.getWriter();  int count = 0;  while (true) { // 模拟持续发送事件  out.println("data: Event " + (count++) + " at " + System.currentTimeMillis());  out.println("event: server-time"); // 可选的事件类型  out.println("retry: 1000\n"); // 推荐客户端在断开连接后等待1秒再重连  // 刷新输出流  out.flush();  // 暂停一段时间再发送下一条消息  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  e.printStackTrace();  break;  }  }  // 注意:在实际应用中,你可能需要一种机制来优雅地关闭连接,而不是使用无限循环  }  
}

在这个示例中,我们创建了一个Servlet来模拟SSE服务。Servlet响应设置了正确的内容类型和字符编码,并使用PrintWriter发送SSE事件。在实际应用中,你可能会使用一个更复杂的逻辑来控制何时发送消息以及如何优雅

相关文章:

  • 【多线程】进程与线程
  • 计算机毕业设计Hadoop+Hive地震预测系统 地震数据分析可视化 地震爬虫 大数据毕业设计 Spark 机器学习 深度学习 Flink 大数据
  • WPF/C#:程序关闭的三种模式
  • 探索Dagster:现代数据编排的利器
  • Opus从入门到精通(一)简介
  • 深层网络:层数多真的更好吗?
  • 解锁ChatGPT:从原理探索到GPT-2的中文实践及性能优化
  • 【安装笔记-20240612-Linux-内网穿透服务之cpolar极点云】
  • Android 10.0 framework层禁止扫描5g wifi功能实现
  • Jtti:ubuntu文件系统根目录磁盘空间不足怎么办
  • 6月11号作业
  • 【数据结构】二叉树:一场关于节点与遍历的艺术之旅
  • 代码随想录算法训练营第36天(py)| 贪心 | 452. 用最少数量的箭引爆气球、435. 无重叠区间、763.划分字母区间
  • 解决SpringBoot在使用AOP切片时DATE类型出现Argument is not assignable to ‘lombok.Data‘ 的问题
  • payable介绍, 编写一个转账的测试合约
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • angular组件开发
  • ERLANG 网工修炼笔记 ---- UDP
  • HTML-表单
  • idea + plantuml 画流程图
  • IP路由与转发
  • js
  • Mithril.js 入门介绍
  • mysql_config not found
  • MySQL几个简单SQL的优化
  • text-decoration与color属性
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 简单易用的leetcode开发测试工具(npm)
  • 使用 Docker 部署 Spring Boot项目
  • 译有关态射的一切
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • ​520就是要宠粉,你的心头书我买单
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • (1)Android开发优化---------UI优化
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (黑马C++)L06 重载与继承
  • (九十四)函数和二维数组
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)C#调用WebService 基础
  • (转)EXC_BREAKPOINT僵尸错误
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .Mobi域名介绍
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET微信公众号开发-2.0创建自定义菜单