问题内容 我使用 Go 已经有一段时间了,但之前从未使用过 SSE。我遇到了一个问题,有人可以提供一个仅发送给特定用户(连接)的服务器发送事件的工作示例吗? 我正在使用 gorilla
我使用 Go 已经有一段时间了,但之前从未使用过 SSE。我遇到了一个问题,有人可以提供一个仅发送给特定用户(连接)的服务器发送事件的工作示例吗?
我正在使用 gorilla - 会话进行身份验证,并且我想使用 UserID 来分隔连接。
或者我应该通过 ajax 使用 5 秒轮询?
非常感谢
这是我发现并尝试过的:
https://GISt.GitHub.com/ismasan/3fb75381cd2deb6bfa9c 它不会发送给个人用户,并且如果连接关闭,go func 也不会停止
Https://github.com/striversity/gotr/blob/master/010-server-sent-event-part-2/main.go 这正是我所需要的,但一旦连接被删除。所以现在,一旦您在私人窗口中关闭并打开浏览器,它就根本无法工作。另外,如上所述,Go 例程继续进行。
创建一个“代理”来将消息分发给连接的用户:
type broker struct {
// users is a map where the key is the user id
// and the value is a slice of channels to connections
// for that user id
users map[string][]chan []byte
// actions is a channel of functions to call
// in the broker's goroutine. the broker executes
// everything in that single goroutine to avoid
// data races.
actions chan func()
}
// run executes in a goroutine. it simply gets and
// calls functions.
func (b *broker) run() {
for a := range b.actions {
a()
}
}
func newbroker() *broker {
b := &broker{
users: make(map[string][]chan []byte),
actions: make(chan func()),
}
go b.run()
return b
}
// adduserchan adds a channel for user with given id.
func (b *broker) adduserchan(id string, ch chan []byte) {
b.actions <- func() {
b.users[id] = append(b.users[id], ch)
}
}
// removeuserchan removes a channel for a user with the given id.
func (b *broker) removeuserchan(id string, ch chan []byte) {
// the broker may be trying to send to
// ch, but nothing is receiving. pump ch
// to prevent broker from getting stuck.
go func() { for range ch {} }()
b.actions <- func() {
chs := b.users[id]
i := 0
for _, c := range chs {
if c != ch {
chs[i] = c
i = i + 1
}
}
if i == 0 {
delete(b.users, id)
} else {
b.users[id] = chs[:i]
}
// close channel to break loop at beginning
// of removeuserchan.
// this must be done in broker goroutine
// to ensure that broker does not send to
// closed goroutine.
close(ch)
}
}
// sendtouser sends a message to all channels for the given user id.
func (b *broker) sendtouser(id string, data []byte) {
b.actions <- func() {
for _, ch := range b.users[id] {
ch <- data
}
}
}
在包级别使用代理声明变量:
var broker = newbroker()
使用代理编写 sse 端点:
func sseEndpoint(w http.ResponseWriter, r *http.Request) {
// I assume that user id is in query string for this example,
// You should use your authentication code to get the id.
id := r.FORMValue("id")
// Do the usual SSE setup.
flusher := w.(http.Flusher)
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
// Create channel to receive messages for this connection.
// Register that channel with the broker.
// On return from the function, remove the channel
// from the broker.
ch := make(chan []byte)
broker.addUserChan(id, ch)
defer broker.removeUserChan(id, ch)
for {
select {
case <-r.Context().Done():
// User closed the connection. We are out of here.
return
case m := <-ch:
// We got a message. Do the usual SSE stuff.
fmt.Fprintf(w, "data: %s\n\n", m)
flusher.Flush()
}
}
}
向您的应用程序添加代码以调用 broker.sendtouser。
--结束END--
本文标题: Golang 服务器向每个用户发送的事件
本文链接: https://lsjlt.com/news/561501.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0