您现在的位置是:首页 > 技术教程 正文

实时通信的服务器推送机制 EventSource(SSE) 简介,附 go 实现示例

admin 阅读: 2024-03-19
后台-插件-广告管理-内容页头部广告(手机)

简介

不知道大家有没有见过 Content-Type:text/event-stream 的请求头,这是 HTML5 中的 EventSource 是一项强大的 API,通过服务器推送实现实时通信。

与 WebSocket 相比,EventSource 提供了一种简单而可靠的单向通信机制(服务器->客户端),实现简单,适用于许多实时应用场景。

本文将介绍 EventSource 的简单使用、与 WebSocket 的对比以及其优缺点,最后对其进行总结。

EventSource

客户端从服务端订阅一条“流”,之后服务端可以发送消息给客户端直到服务端或者客户端关闭该“流”,所以 EventSource 也叫作 SSE(server-sent-event)。

  • EventSource 是 HTML5 中的一项 API,用于在客户端和服务器之间建立持久的、单向的通信连接。
  • 它基于 HTTP 协议,通过服务器推送的方式向客户端发送实时事件通知。
  • 客户端通过添加事件侦听器来捕获事件并执行相应的操作。

简单使用

示例:
服务器端使用 Go 创建了一个路由 /events,当客户端通过 EventSource 对象连接到该路由时,服务器会不断地发送事件流(每隔2秒发送一个事件)。客户端的 HTML 页面中使用 JavaScript 创建了一个 EventSource 对象,通过 onmessage 事件,将接收到的事件数据添加到页面中。如果发生错误,客户端会关闭 EventSource 连接。

文件结构如下

程序目录 - main.go - c1.html
  • 1
  • 2
  • 3

go 服务

package main import ( "fmt" "gopkg.in/antage/eventsource.v1" "log" "net/http" "time" ) func main() { es := eventsource.New(nil, nil) defer es.Close() http.Handle("/", http.FileServer(http.Dir("./"))) http.Handle("/events", es) go func() { for { // 每2秒发送一条当前时间消息,并打印对应客户端数量 es.SendEventMessage(fmt.Sprintf("hello, now is: %s", time.Now()), "", "") log.Printf("Hello has been sent (consumers: %d)", es.ConsumersCount()) time.Sleep(2 * time.Second) } }() log.Println("Open URL http://localhost:8080/ in your browser.") err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal(err) } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

前端 HTML

DOCTYPE html> <html> <head> <title>SSE testtitle> <script type="text/javascript"> window.addEventListener("DOMContentLoaded", function () { var evsrc = new EventSource("http://localhost:8080/events"); var msgEvent = function (ev) { document.getElementById("log") .insertAdjacentHTML("beforeend", "
  • " + ev.data + "
  • "
    ); } evsrc.onmessage = msgEvent; //evsrc.addEventListener("message", msgEvent) evsrc.onerror = function (ev) { console.log("readyState = " + ev.currentTarget.readyState); } })
    script> head> <body> <h1>SSE testh1> <div> <ul id="log"> ul> div> body> html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    服务启动后访问 http://localhost:8080/c1.html 可见如下页面
    在这里插入图片描述

    和 websocket 的对比

    EventSource 的优点

    • 简单易用:EventSource 使用简单,基于标准的 HTTP 协议,无需复杂的握手过程。
    • 自动重连:EventSource 具有内置的重连机制,确保连接中断后自动重新连接。
    • 轻量级:EventSource 使用长轮询机制,消耗的资源相对较少,适合低带宽环境。
    • 跨域支持:EventSource 允许在跨域环境下进行通信,通过适当的响应头授权来自不同域的客户端连接。

    EventSource 的缺点

    • 单向通信:EventSource 只支持服务器向客户端的单向通信,无法实现客户端向服务器的实时交互。
    • 较低的浏览器支持:尽管现代浏览器广泛支持 EventSource,但在一些较旧的浏览器中可能不完全支持。

    WebSocket 的优点

    • 双向通信:WebSocket 支持全双工通信,客户端和服务器可以在同一连接上进行双向数据交换。
    • 实时性和效率:WebSocket 具有低延迟和高效性能,适用于需要快速、实时响应的应用。
    • 大规模应用:WebSocket适用于复杂的、大规模的实时应用,如在线游戏、协同编辑等。

    WebSocket 的缺点

    • 复杂性:WebSocket协议的握手过程相对复杂,需要服务器和客户端实现特定的协议逻辑。
    • 难以穿越防火墙和代理服务器:WebSocket的特殊协议可能会受到防火墙和代理服务器的限制。

    总结

    EventSource 是 HTML5 中一个强大的 API,提供了简单可靠的服务器推送机制,用于实现实时通信。

    与 WebSocket 相比,EventSource 的优势在于其简单易用、自动重连、轻量级和跨域支持。然而,它也有一些限制,如单向通信和较低的浏览器支持。相比之下,WebSocket 适用于双向通信、大规模应用和实时性要求较高的场景,但其复杂性和穿越防火墙的挑战也需要考虑。

    总的来说,EventSource 是一种非常有用的 API,适用于许多实时应用场景,如实时股票报价、即时聊天、实时通知等。它提供了一种简单而可靠的方式来建立服务器推送连接,并实现实时更新和通知。如果应用程序只需要服务器向客户端单向推送数据,EventSource 是一个不错的选择。然而,如果需要双向通信或更高级的实时功能,WebSocket 可能更适合。

    参考

    • Mozilla Developer Network (MDN) - EventSource
    • Stream Updates with Server-Sent Events
    标签:
    声明

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    在线投稿:投稿 站长QQ:1888636

    后台-插件-广告管理-内容页尾部广告(手机)
    关注我们

    扫一扫关注我们,了解最新精彩内容

    搜索
    排行榜