如何在 Go 语言中实现 Server-Sent Events (SSE)

Server-Sent Events (SSE) 是一种服务器向客户端推送事件的技术。这种技术允许服务器异步向客户端发送事件,而无需客户端进行请求。这对于实时应用程序非常有用,例如聊天应用程序,股票价格更新等。

file

创建HTTP服务器

首先,我们需要创建一个HTTP服务器。在Go中,我们可以使用net/http包来实现这个目标。

package main

import (
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 这里会放置我们的SSE处理器代码
    })

    http.ListenAndServe(":8080", nil)
}

实现SSE处理器

在HTTP服务器中,我们需要实现一个SSE处理器。这个处理器将设置正确的HTTP头,并持续向客户端发送数据。

package main

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

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 设置正确的头以启用SSE
        w.Header().Set("Content-Type", "text/event-stream")
        w.Header().Set("Cache-Control", "no-cache")
        w.Header().Set("Connection", "keep-alive")

        // 每秒向客户端发送一个事件
        for {
            fmt.Fprintf(w, "data: The server time is: %v\n\n", time.Now())
            w.(http.Flusher).Flush() // 刷新数据到客户端
            time.Sleep(time.Second)
        }
    })

    http.ListenAndServe(":8080", nil)
}

请求参数

如果你想在你的SSE处理器中处理请求体,你需要在你的处理器中解析这个请求体。这可以通过使用r.Body来实现,r*http.Request类型的实例,它包含了HTTP请求的所有信息。

下面是一个例子,假设你的请求体是JSON格式,你可以使用encoding/json包来解析它:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

type Message struct {
    Text string `json:"text"`
}

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // 设置正确的头以启用SSE
        w.Header().Set("Content-Type", "text/event-stream")
        w.Header().Set("Cache-Control", "no-cache")
        w.Header().Set("Connection", "keep-alive")

        // 解析请求体
        body, err := ioutil.ReadAll(r.Body)
        defer r.Body.Close()
        if err != nil {
            http.Error(w, "Error reading request body", http.StatusInternalServerError)
            return
        }

        var msg Message
        err = json.Unmarshal(body, &msg)
        if err != nil {
            http.Error(w, "Error parsing request body", http.StatusBadRequest)
            return
        }

        // 使用请求体中的消息向客户端发送事件
        for {
            fmt.Fprintf(w, "data: The message is: %v\n\n", msg.Text)
            w.(http.Flusher).Flush() // 刷新数据到客户端
            time.Sleep(time.Second)
        }
    })

    http.ListenAndServe(":8080", nil)
}

在这个例子中,我们假设请求体是一个包含text字段的JSON对象。我们创建了一个Message结构体来对应这个格式,然后使用json.Unmarshal函数来解析请求体。解析后的消息将被用来发送给客户端。

注意,这个处理器现在不仅仅是一个SSE处理器,它也处理了POST请求。如果你的应用程序需要处理多种类型的请求,你可能需要将这些代码分离到不同的处理器中。

编写客户端JavaScript代码

在客户端,我们需要编写JavaScript代码来接收和处理服务器发送的事件。这可以通过使用EventSource对象来实现。

<!DOCTYPE html>
<html>
<body>
<script>
var source = new EventSource("http://localhost:8080");

source.onmessage = function(event) {
  document.body.innerHTML += event.data + "<br>";
};
</script>
</body>
</html>

运行和测试

最后,我们可以运行我们的Go服务器,并在浏览器中打开我们的HTML文件来测试我们的SSE实现。如果一切正常,我们应该每秒在浏览器中看到一个新的服务器时间。

js中await的详细用法
Nginx 通过 certbot 为网站自动配置 SSL 证书并续期
标签:

发表我的评论

电子邮件地址不会被公开。 必填项已用*标注

39 + 26 =

ajax-loader