使用Python和Go实现服务器发送事件(SSE)🚀

在当今的交互式web应用程序中,实时数据更新在增强用户体验方面起着至关重要的作用。在实时通信的各种技术中,SSE在众多解决方案脱颖而出。SSE允许服务器通过HTTP向客户端推送实时更新。

为什么选择SSE?🤔

服务器发送事件是HTML5规范的一部分,专门用于将事件从服务器推送到客户端。它的简单性、自动重新连接和事件跟踪功能使其非常适合数据流的场景。在单向数据流情况下,SSE表现尤其出色。

概述📚

SSE是一种服务器向浏览器实时推送消息的技术。它是HTML5规范的一部分,主要涉及:

  1. 通信协议:使用HTTP。
  2. 事件对象:在浏览器端可用。

WebSockets也是一种实时通信技术,但它们有不同之处:

SSE WebSockets
基于HTTP 基于TCP
单向(服务器到客户端) 全双工(双向)
轻量级和简单 更复杂的
内置重新连接和消息跟踪 需要手动实现这些功能
文本或Base64和gzip压缩的二进制文件 支持各种数据类型
支持自定义事件类型 不支持自定义事件类型
HTTP/1.1或HTTP/2限制连接数量 无限连接

服务器实现🌐

协议实现

本质上,浏览器发起一个HTTP请求,服务器用HTTP状态进行响应,包括以下标头:

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

SSE指定事件流的MIME类型必须为 text/event-stream ,浏览器不应该缓存数据,并且连接应该是持久的( keep-alive )。

消息格式

事件流是使用UTF-8编码的文本或Base64编码的二进制消息,并使用gzip压缩。每条消息由一行或多行字段组成,格式为 field-name : field-value 。每个字段以 \n 结尾。以冒号开头的行是注释,会被浏览器忽略。每个推送可以由多个消息组成,以空行分隔( \n\n )。

关键字段包括:

  • event :事件类型。
  • id :事件ID,浏览器跟踪最后接收到的事件用来重新连接服务。
  • retry :浏览器在连接失败后重新尝试连接所需的等待时间(ms)。
  • data :消息数据。

示例:Python实现SSE

Python 复制代码
from flask import Flask, Response

app = Flask(__name__)


@app.route('/events')
def sse_handler():
    def generate():
        paragraph = [
            "Hello, this is an example of a continuous text output.",
            "It contains multiple sentences, each of which will be sent to the client as an event.",
            "This is to simulate the functionality of Server-Sent Events (SSE).",
            "We can use this method to push real-time updates.",
            "End of sample text, thank you!",
        ]

        for sentence in paragraph:
            yield f"data: {sentence}\n\n"

            import time
            time.sleep(1)

    return Response(generate(), mimetype='text/event-stream')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8081, debug=True)

示例:Go实现SSE

Go 复制代码
package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("/events", sseHandler)

    fmt.Println("Starting server on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatalf("Server error: %v", err)
    }
}

func sseHandler(w http.ResponseWriter, r *http.Request) {
    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    // Change the output here to a specific text
    paragraph := []string{
        "Hello, this is an example of a continuous text output.",
        "It contains multiple sentences, each of which will be sent to the client as an event.",
        "This is to simulate the functionality of Server-Sent Events (SSE).",
        "We can use this method to push real-time updates.",
        "End of sample text, thank you!",
    }

    for _, sentence := range paragraph {
        _, err := fmt.Fprintf(w, "data: %s\n\n", sentence)
        if err != nil {
            return
        }
        flusher.Flush()
        time.Sleep(1 * time.Second) // Wait 1 second before sending the next piece of text
    }
}

浏览器API️

在客户端,JavaScript的 EventSource API允许您创建一个 EventSource 对象来侦听服务器发送的事件。一旦连接上,服务器就可以向浏览器发送事件消息。浏览器通过监听 onmessageonopenonerror 事件来处理这些消息。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SSE Example 🌟</title>
</head>
<body>
    <h1>Server-Sent Events Example 🚀</h1>
    <div id="messages"></div>
    <script>
        window.onload = function() {
            if (typeof(EventSource) !== "undefined") {
                const eventSource = new EventSource('/events');

                eventSource.onmessage = function(event) {
                    const newElement = document.createElement("p");
                    newElement.textContent = "Message: " + event.data;

                    document.getElementById("messages").appendChild(newElement);
                };

                eventSource.onerror = function(event) {
                    console.error("Error occurred: ", event);
                    const newElement = document.createElement("p");
                    newElement.textContent = "An error occurred while connecting to the event source.";
                    document.getElementById("messages").appendChild(newElement);
                    eventSource.close(); 
                };
            } else {
                document.getElementById("messages").textContent = "Sorry, your browser does not support server-sent events...";
            }
        };
    </script>
</body>
</html>

SSE调试

目前,许多流行的工具,如Postman、Insomnia、Bruno和ThunderClient缺乏对服务器发送事件SSE的足够支持。在开发过程中,这种限制会让人非常沮丧。幸运的是,我最近遇到了EchoAPI,这个工具提供了出色的SSE调试功能。这个发现极大地改善了我的工作流程,提高了效率和生产力。

如果您正在使用SSE或进行API调试,我强烈建议您尝试一下EchoAPI。它可以彻底改变您的调试体验并简化您的开发工作。更多信息请访问 www.echoapi.com. 🚀

示例:SSE的EchoAPI客户端

在EchoAPI中,使用SSE接口非常简单。只需输入URL,填写相关参数,然后点击"发送"即可看到您的请求结果。🚀

相关推荐
野犬寒鸦35 分钟前
Linux常用命令详解(下):打包压缩、文本编辑与查找命令
linux·运维·服务器·数据库·后端·github
huohuopro1 小时前
thinkphp模板文件缺失没有报错/thinkphp无法正常访问控制器
后端·thinkphp
cainiao0806054 小时前
《Spring Boot 4.0新特性深度解析》
java·spring boot·后端
-曾牛4 小时前
Spring AI 与 Hugging Face 深度集成:打造高效文本生成应用
java·人工智能·后端·spring·搜索引擎·springai·deepseek
南玖yy4 小时前
C/C++ 内存管理深度解析:从内存分布到实践应用(malloc和new,free和delete的对比与使用,定位 new )
c语言·开发语言·c++·笔记·后端·游戏引擎·课程设计
计算机学姐5 小时前
基于SpringBoot的小区停车位管理系统
java·vue.js·spring boot·后端·mysql·spring·maven
BUG制造机.5 小时前
Go 语言 slice(切片) 的使用
开发语言·后端·golang
小鸡脚来咯5 小时前
请求参数:Header 参数,Body 参数,Path 参数,Query 参数分别是什么意思,什么样的,分别通过哪个注解获取其中的信息
java·spring boot·后端
天上掉下来个程小白6 小时前
添加购物车-02.代码开发
java·服务器·前端·后端·spring·微信小程序·苍穹外卖
幽络源小助理8 小时前
懒人美食帮SpringBoot订餐系统开发实现
java·spring boot·后端·美食