Server-Sent Events一种允许服务器向客户端发送实时更新的 Web API

news2025/4/18 9:26:50

Server-Sent Events(SSE)是一种允许服务器向客户端发送实时更新的 Web API。它基于 HTTP 协议,提供了一种单向的、服务器到客户端的通信机制,客户端可以通过监听服务器发送的事件来接收实时数据。下面从原理、使用场景、代码示例等方面进行详细介绍。

原理

  1. 连接建立:客户端通过创建一个 EventSource 对象并指定服务器的 URL 来发起一个 HTTP 请求,建立与服务器的连接。这个连接是一个持久的、单向的 HTTP 连接,服务器可以随时向客户端发送数据。
  2. 数据发送:服务器以特定的格式(通常是 text/event-stream)向客户端发送事件流。每个事件由事件类型、数据和可选的 ID 组成,使用简单的文本格式进行编码。
  3. 事件监听:客户端通过监听 EventSource 对象的不同事件(如 messageopenerror)来处理服务器发送的数据。当接收到新的事件时,会触发相应的事件处理函数。
  4. 重连机制:如果连接中断,EventSource 会自动尝试重新连接到服务器,确保数据的连续性。

使用场景

  • 实时新闻更新:新闻网站可以使用 SSE 实时向用户推送最新的新闻文章。
  • 股票行情:金融应用可以通过 SSE 实时更新股票价格和市场数据。
  • 聊天应用:在聊天应用中,服务器可以使用 SSE 向客户端实时推送新消息。
  • 监控系统:监控系统可以使用 SSE 实时向管理员发送服务器状态、性能指标等信息。

代码示例

下面是一个使用 Server-Sent Events 的简单示例,包括服务器端和客户端(使用 JavaScript)。

服务器端代码(go +gin)
// StreamChat 流式输出聊天信息
// @Summary 流式输出聊天信息
// @Description 流式输出聊天信息,客户端可以实时接收数据。
// @Tags Chat
// @Accept  json
// @Produce  text/event-stream
// @Success 200 {string} string	"data: 1\n\n"
// @Router /web/StreamChat [get]
func (u ChatController) StreamChat(c *gin.Context) {
	// 设置响应头,指定内容类型为流式输出
	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")
	c.Writer.Header().Set("Access-Control-Allow-Origin", "*")

	// 循环输出 1 到 100 的数字
	for i := 1; i <= 100; i++ {
		// 发送数据
		c.Writer.Write([]byte("data: " + string(i+'0') + "\n\n"))
		// 刷新缓冲区,将数据发送给客户端
		c.Writer.(http.Flusher).Flush()
		// 每隔 1 秒输出一个数字
		time.Sleep(time.Second)
	}

}


# Routers
web.GET("/StreamChat", func(c *gin.Context) {
			controllers.ChatController{}.StreamChat(c)
		})
客户端代码(HTML + JavaScript)
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Server-Sent Events Example</title>
</head>

<body>
    <h1>Real-time Updates</h1>
    <ul id="messages"></ul>

    <script>
        const eventSource = new EventSource('/web/StreamChat');

        eventSource.onmessage = (event) => {
            const messagesList = document.getElementById('messages');
            const newMessage = document.createElement('li');
            newMessage.textContent = event.data;
            messagesList.appendChild(newMessage);
        };

        eventSource.onerror = (error) => {
            console.error('EventSource failed:', error);
        };
    </script>
</body>

</html>

代码解释

  • 服务器端:设置响应头:在 streamNumbers 函数里,设置了一系列响应头,以此确保响应为流式输出,并且防止缓存。循环输出数字:借助 for 循环,从 1 到 100 输出数字,每次输出一个数字后,刷新缓冲区把数据发送给客户端。定时输出:使用 time.Sleep 函数,使每个数字的输出间隔为 1 秒。

  • 客户端:创建一个 EventSource 对象并监听 /web/StreamChat 事件,当接收到新的事件时,将事件数据添加到页面的列表中。同时监听 error 事件,处理连接错误。

优缺点

优点
  • 简单易用:基于 HTTP 协议,使用简单,不需要复杂的握手和连接管理。
  • 自动重连:客户端会自动处理连接中断和重连,确保数据的连续性。
  • 文本格式:数据以文本格式传输,易于理解和处理。
缺点
  • 单向通信:只能从服务器向客户端发送数据,不支持客户端向服务器发送数据。
  • 浏览器兼容性:虽然现代浏览器大多支持 SSE,但在一些旧版本的浏览器中可能不支持。
  • 性能开销:与 WebSocket 相比,SSE 的性能开销相对较大,因为它是基于 HTTP 协议的。

Server-Sent Events 是一种简单、易用的实时通信机制,适用于服务器向客户端单向推送实时数据的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2332587.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

彻底解决VS2008编译错误:fatal error C1083 无法打开包括文件“stdint.h“

彻底解决VS2008编译错误&#xff1a;fatal error C1083 无法打开包括文件"stdint.h" 一、错误现象与本质原因 当在Visual Studio 2008中编译包含C99标准整数类型&#xff08;如int8_t、uint32_t&#xff09;的代码时&#xff0c;常出现以下编译错误&#xff1a; f…

react从零开始的基础课

全文约5万字。 1.hello,.. // App.jsx import { useState } from react import reactLogo from ./assets/react.svg import viteLogo from /vite.svg import ./App.cssfunction App() {const [count, setCount] useState(0)return (<><Greeting name"world&qu…

算法题型讲解

一.双指针 主要分为俩种类型&#xff1a; 1.左右指针&#xff1a;双指针指向开头&#xff0c;以一定标准移动或交换&#xff0c;对区域进行划分&#xff0c;或找到特殊点的位置 &#xff08;如&#xff1a;快慢指针判断有无环&#xff0c;移动零&#xff09; 2.对撞指针&am…

Redis和数据库一致性问题

操作模拟 1、先更新数据库还是先更新缓存&#xff1f; 1.1先更新缓存&#xff0c;再更新数据库 按并发的角度来说&#xff0c;有两个线程A、B&#xff0c;操作同一个数据&#xff0c;线程A先更新缓存为1&#xff0c;在线程A更新数据库之前&#xff0c;这时候线程B进来&#…

第R8周:RNN实现阿尔茨海默病诊断(pytorch)

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营]中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊]** 本人往期文章可查阅&#xff1a; 深度学习总结 一、准备工作 &#x1f3e1; 我的环境&#xff1a; 语言环境&#xff1a;Python3.1…

C++基础精讲-02

文章目录 1.C/C申请、释放堆空间的方式对比1.1C语言申请、释放堆空间1.2C申请、释放堆空间1.2.1 new表达式申请数组空间 1.3回收空间时的注意事项1.4malloc/free 和 new/delete 的区别 2.引用2.1 引用的概念2.2 引用的本质2.3 引用与指针的联系与区别2.4 引用的使用场景2.4.1 引…

【网络安全】Linux 命令大全

未经许可,不得转载。 文章目录 前言正文文件管理文档编辑文件传输磁盘管理磁盘维护网络通讯系统管理系统设置备份压缩设备管理其它命令前言 在网络安全工作中,熟练掌握 Linux 系统中的常用命令对于日常运维、日志分析和安全排查等任务至关重要。 以下是常用命令的整理汇总,…

C++学习之ORACLE①

目录 1.ORACLE数据库简介 2..ORACLE数据库安装 3..ORACLE体系结构 4..ORACLE基本概念 5..ORACLE基本元素 6..ORACLE数据库启动和关闭 7.SQLPLUS登录ORACLE数据库相关操作 8.SQLPLUS的基本操作 9.oracle中上课使用的方案 10.SQL语言分类 11.SQL中的select语句语法和注…

企业级开发SpringBoost玩转Elasticsearch

案例 Spring Boot 提供了 spring-data-elasticsearch 模块&#xff0c;可以方便地集成 Elasticsearch。 下面我们将详细讲解如何在 Spring Boot 中使用 Elasticsearch 8&#xff0c;并提供示例代码。 1. 添加依赖: 首先&#xff0c;需要在 pom.xml 文件中添加 spring-data-e…

从零开始的图论讲解(1)——图的概念,图的存储,图的遍历与图的拓扑排序

目录 前言 图的概念 1. 顶点和边 2. 图的分类 3. 图的基本性质 图的存储 邻接矩阵存图 邻接表存图 图的基本遍历 拓扑排序 拓扑排序是如何写的呢? 1. 统计每个节点的入度 2. 构建邻接表 3. 将所有入度为 0 的节点加入队列 4. 不断弹出队头节点&#xff0c;更新其…

SpringBoot框架—启动原理

1.SpringBootApplication注解 在讲解启动原理之前先介绍一个非常重要的注解SpringBootApplication&#xff0c;这个注解在Springboot程序的入口文件Application.java中必须添加。SpringBootApplication是一个整合了三个核心注解的组合注解。 三个核心注解的作用机制&#xff1…

怎么检查网站CDN缓存是否生效

为什么要使用CDN缓存&#xff1f; 网站使用缓存可显著提升加载速度&#xff0c;减少服务器负载和带宽消耗&#xff0c;优化用户体验&#xff0c;增强架构稳定性&#xff0c;助力SEO优化&#xff0c;实现资源高效利用与性能平衡。 通过合理配置 CDN 缓存策略&#xff0c;可降低…

【自然语言处理】深度学习中文本分类实现

文本分类是NLP中最基础也是应用最广泛的任务之一&#xff0c;从无用的邮件过滤到情感分析&#xff0c;从新闻分类到智能客服&#xff0c;都离不开高效准确的文本分类技术。本文将带您全面了解文本分类的技术演进&#xff0c;从传统机器学习到深度学习&#xff0c;手把手实现一套…

vba讲excel转换为word

VBA将excel转换为word Sub ExportToWordFormatted() 声明变量Dim ws As Worksheet 用于存储当前活动的工作表Dim rng As Range 用于存储工作表的使用范围&#xff08;即所有有数据的单元格&#xff09;Dim rowCount As Long, colCount As Long 用于存储数据范围的行数和列数…

ubuntu安装openWebUI和Dify【自用详细版】

系统版本&#xff1a;ubuntu24.04LTS 显卡&#xff1a;4090 48G 前期准备 先安装好docker和docker-compose&#xff0c;可以参考我之前文章安装&#xff1a; ubuntu安装docker和docker-compose【简单详细版】 安装openWebUI 先docker下载ollama docker pull ghcr.nju.edu.c…

基于Flask的勒索病毒应急响应平台架构设计与实践

基于Flask的勒索病毒应急响应平台架构设计与实践 序言&#xff1a;安全工程师的防御视角 作为从业十年的网络安全工程师&#xff0c;我深刻理解勒索病毒防御的黄金时间法则——应急响应速度每提升1分钟&#xff0c;数据恢复成功率将提高17%。本文介绍的应急响应平台&#xff…

spark数据清洗案例:流量统计

一、项目背景 在互联网时代&#xff0c;流量数据是反映用户行为和业务状况的重要指标。通过对流量数据进行准确统计和分析&#xff0c;企业可以了解用户的访问习惯、业务的热门程度等&#xff0c;从而为决策提供有力支持。然而&#xff0c;原始的流量数据往往存在格式不规范、…

list的使用以及模拟实现

本章目标 1.list的使用 2.list的模拟实现 1.list的使用 在stl中list是一个链表,并且是一个双向带头循环链表,这种结构的链表是最优结构. 因为它的实现上也是一块线性空间,它的使用上是与string和vector类似的.但相对的因为底层物理结构上它并不像vector是线性连续的,它并没有…

【今日三题】小乐乐改数字 (模拟) / 十字爆破 (预处理+模拟) / 比那名居的桃子 (滑窗 / 前缀和)

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;每日两三题 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 小乐乐改数字 (模拟)十字爆破 (预处理模拟&#xff09;比那名居的桃子 (滑窗 / 前缀和) 小乐乐改数字 (模拟) 小乐乐改数字…

基于 Qt 的图片处理工具开发(一):拖拽加载与基础图像处理功能实现

一、引言 在桌面应用开发中&#xff0c;图片处理工具的核心挑战在于用户交互的流畅性和异常处理的健壮性。本文以 Qt为框架&#xff0c;深度解析如何实现一个支持拖拽加载、亮度调节、角度旋转的图片处理工具。通过严谨的文件格式校验、分层的架构设计和用户友好的交互逻辑&am…