关于 text/event-stream:
text/event-stream 是一种特殊的 MIME 类型,用于服务器向客户端发送事件流。这种技术主要用于实现服务器发送事件(Server-Sent Events, SSE)。以下是对 text/event-stream 的几个关键理解点:
1. 单向通信:与 WebSocket 不同,SSE 是单向的,只能从服务器向客户端发送数据。
2. 基于 HTTP:它使用标准的 HTTP 协议,不需要特殊的协议支持。
3. 自动重连:客户端会自动尝试重新连接,如果连接断开。
4. 数据格式:事件流的数据格式简单,由文本行组成,每个事件之间用空行分隔。
5. 事件类型:可以指定不同的事件类型,允许客户端针对不同类型的事件进行不同的处理。
6. 实时更新:适用于需要服务器主动推送数据的场景,如实时通知、股票行情更新等。
7. 浏览器支持:大多数现代浏览器都支持 SSE。
8. 轻量级:相比 WebSocket,SSE 更加轻量,适用于单向数据流的场景。
以下是一个使用 Go 实现的简单服务器,它每秒向客户端发送一次当前时间:
package main
import (
"fmt"
"log"
"net/http"
"time"
)
func main() {
http.HandleFunc("/events", eventsHandler)
log.Println("Server is running on http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func eventsHandler(w http.ResponseWriter, r *http.Request) {
// 设置响应头
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
// 创建一个通道来发送信号,以便在客户端断开连接时停止发送事件
clientClosed := r.Context().Done()
for {
select {
case <-clientClosed:
return // 客户端断开连接,退出函数
default:
// 发送事件
fmt.Fprintf(w, "data: The server time is: %v\n\n", time.Now().Format(time.RFC3339))
w.(http.Flusher).Flush()
time.Sleep(time.Second) // 每秒发送一次
}
}
}
//
这个 Go 示例的工作原理如下:
我们创建了一个 HTTP 服务器,监听在 8080 端口。
/events 路径被映射到 eventsHandler 函数。
在 eventsHandler 函数中:
我们设置了适当的响应头,包括 Content-Type: text/event-stream。
我们使用一个无限循环来持续发送事件。
每次循环,我们发送当前时间作为事件数据。
我们使用 Flush() 来确保数据立即发送给客户端。
我们使用 time.Sleep() 来控制发送频率。
我们使用 r.Context().Done() 来检测客户端是否断开连接,如果断开则停止发送事件。
要使用这个服务器,客户端(如 Web 浏览器)可以使用 EventSource API 来连接和接收事件:
const eventSource = new EventSource('http://localhost:8080/events');
eventSource.onmessage = function(event) {
console.log(event.data);
};
