golang gin sse 服务端向客户端推消息

5,555 阅读1分钟

很多人可能不知道,服务端向客户端推送消息,其实除了可以用WebSocket这种耳熟能详的机制外,还有一种服务器发送事件(Server-sent events),简称SSE

SSE它是基于HTTP协议的,我们知道一般意义上的HTTP协议是无法做到服务端主动向客户端推送消息的,但SSE是个例外,它变换了一种思路。 很多人可能不知道,服务端向客户端推送消息,其实除了可以用WebSocket这种耳熟能详的机制外,还有一种服务器发送事件(Server-sent events),简称SSE

SSE它是基于HTTP协议的,我们知道一般意义上的HTTP协议是无法做到服务端主动向客户端推送消息的,但SSE是个例外,它变换了一种思路。

在某些情况下,不需要从客户端发送数据。而你只需要一些服务器操作的更新。比如:站内信、未读消息数、状态更新、股票行情、监控数量等场景,SEE不管是从实现的难易和成本上都更加有优势。此外,SSE 具有WebSockets在设计上缺乏的多种功能,例如:自动重新连接事件ID发送任意事件的能力。

图片.png

接下来看代码:

golang

package main

import (
   "fmt"
   "github.com/gin-gonic/gin"
   "gopkg.in/antage/eventsource.v1"
   "log"
   "net/http"
)

func main() {
   es := eventsource.New(nil, nil)
   defer es.Close()
   r := gin.Default()

   {
      r.GET("/events", esSSE)
      r.Run(":8080")
   }
}

func esSSE(c *gin.Context) {
   w := c.Writer

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

   _, ok := w.(http.Flusher)

   if !ok {
      log.Panic("server not support") //浏览器不兼容
   }

   _, err := fmt.Fprintf(w, "data: %s\n\n", "dsdf")
   if err != nil {
      return
   }
}

html

<!DOCTYPE html>
<html>
<head>
    <title>SSE test</title>
    <script type="text/javascript">
        window.addEventListener("DOMContentLoaded", function () {
            var evsrc = new EventSource("http://localhost:8080/events");
            evsrc.onmessage = function (ev) {
                document.getElementById("log")
                    .insertAdjacentHTML("beforeend", "<li>" + ev.data + "</li>");
            }
            evsrc.onerror = function (ev) {
                console.log("readyState = " + ev.currentTarget.readyState);
            }
        })
    </script>
</head>
<body>
<h1>SSE test</h1>
<div>
    <ul id="log">
    </ul>
</div>
</body>
</html>

效果

图片.png