英文:
Eventsource golang : how to detect client disconnection?
问题
我正在使用https://github.com/antage/eventsource包基于Twitter标签开发聊天室,并使用服务器发送事件。我遇到了一个关于客户端断开连接的问题。我在一个goroutine中向客户端发送消息,但是当客户端断开连接时,goroutine仍然在运行。
我不知道如何在服务器端检测到客户端已断开连接。
以下是代码示例:
func (sh StreamHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
es := eventsource.New(
&eventsource.Settings{
Timeout: 2 * time.Second,
CloseOnTimeout: true,
IdleTimeout: 2 * time.Second,
Gzip: true,
},
func(req *http.Request) [][]byte {
return [][]byte{
[]byte("X-Accel-Buffering: no"),
[]byte("Access-Control-Allow-Origin: *"),
}
},
)
es.ServeHTTP(resp, req)
go func() {
var id int
for {
id++
time.Sleep(1 * time.Second)
es.SendEventMessage("blabla", "message", strconv.Itoa(id))
}
}()
}
请问有什么我可以帮助你的吗?
英文:
I'm developing chat rooms based on Twitter hashtag with Server sent events, with the package https://github.com/antage/eventsource
I have a problem concerning the disconnection of the client. I run a goroutine to send messages to the client, but when the client disconnects, the goroutine still runs.
I don't know how to detect on the server side that the client is disconnected.
func (sh StreamHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
es := eventsource.New(
&eventsource.Settings{
Timeout: 2 * time.Second,
CloseOnTimeout: true,
IdleTimeout: 2 * time.Second,
Gzip: true,
},
func(req *http.Request) [][]byte {
return [][]byte{
[]byte("X-Accel-Buffering: no"),
[]byte("Access-Control-Allow-Origin: *"),
}
},
)
es.ServeHTTP(resp, req)
go func() {
var id int
for {
id++
time.Sleep(1 * time.Second)
es.SendEventMessage("blabla", "message", strconv.Itoa(id))
}
}()
}
答案1
得分: 11
截至2018年12月,显然CloseNotifier已被弃用。推荐的解决方案是使用Request
上下文。以下代码对我有效:
done := make(chan bool)
go func() {
<-req.Context().Done()
done <- true
}()
<-done
英文:
As of December 2018, apparently CloseNotifier is deprecated. The recommended solution is to use the Request
Context. The following worked for me:
done := make(chan bool)
go func() {
<-req.Context().Done()
done <- true
}()
<-done
答案2
得分: 6
你可以使用CloseNotifier来判断底层的HTTP连接是否关闭。例如:
notify := w.(http.CloseNotifier).CloseNotify()
go func() {
<-notify
// 连接关闭,进行清理等操作
}()
希望对你有帮助。
英文:
You can use CloseNotifier which lets you know if the underlying http connection has closed. Like:
notify := w.(http.CloseNotifier).CloseNotify()
go func() {
<-notify
// connection close, do cleanup, etc.
}()
HTH
答案3
得分: 3
你可以检查ConsumersCount()
函数:
go func() {
var id int
for es.ConsumersCount() > 0 {
id++
es.SendEventMessage("blabla", "message", strconv.Itoa(id))
time.Sleep(1 * time.Second)
}
fmt.Println("closed")
}()
这种方法可能有点巧妙,但似乎可以工作。
你可能最好使用其他包或自己编写代码,这样你可以更好地控制goroutine的生命周期。你可以在.Write
方法中检测到连接关闭(该包没有公开该方法)。
如果你想要的话,这里有一个使用TCP的聊天服务器示例:chat-server。
还有一个配套的视频教程:tutorial。
对于SSE,相同的基本模式应该适用。
英文:
You could check ConsumersCount()
:
go func() {
var id int
for es.ConsumersCount() > 0 {
id++
es.SendEventMessage("blabla", "message", strconv.Itoa(id))
time.Sleep(1 * time.Second)
}
fmt.Println("closed")
}()
Kinda hacky, but it seems to work.
You may be better off using a different package or rolling your own so you could have better control over the lifetime of your goroutines. You can detect a closed connection on .Write
(which this package isn't exposing).
If you want here's an example chat server in TCP: chat-server.
And a video tutorial to go with it: tutorial.
The same basic pattern should work for SSE.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论