Eventsource golang : how to detect client disconnection?

huangapple go评论120阅读模式
英文:

Eventsource golang : how to detect client disconnection?

问题

我正在使用https://github.com/antage/eventsource包基于Twitter标签开发聊天室,并使用服务器发送事件。我遇到了一个关于客户端断开连接的问题。我在一个goroutine中向客户端发送消息,但是当客户端断开连接时,goroutine仍然在运行。

我不知道如何在服务器端检测到客户端已断开连接。

以下是代码示例:

  1. func (sh StreamHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
  2. es := eventsource.New(
  3. &eventsource.Settings{
  4. Timeout: 2 * time.Second,
  5. CloseOnTimeout: true,
  6. IdleTimeout: 2 * time.Second,
  7. Gzip: true,
  8. },
  9. func(req *http.Request) [][]byte {
  10. return [][]byte{
  11. []byte("X-Accel-Buffering: no"),
  12. []byte("Access-Control-Allow-Origin: *"),
  13. }
  14. },
  15. )
  16. es.ServeHTTP(resp, req)
  17. go func() {
  18. var id int
  19. for {
  20. id++
  21. time.Sleep(1 * time.Second)
  22. es.SendEventMessage("blabla", "message", strconv.Itoa(id))
  23. }
  24. }()
  25. }

请问有什么我可以帮助你的吗?

英文:

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.

  1. func (sh StreamHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
  2. es := eventsource.New(
  3. &eventsource.Settings{
  4. Timeout: 2 * time.Second,
  5. CloseOnTimeout: true,
  6. IdleTimeout: 2 * time.Second,
  7. Gzip: true,
  8. },
  9. func(req *http.Request) [][]byte {
  10. return [][]byte{
  11. []byte("X-Accel-Buffering: no"),
  12. []byte("Access-Control-Allow-Origin: *"),
  13. }
  14. },
  15. )
  16. es.ServeHTTP(resp, req)
  17. go func() {
  18. var id int
  19. for {
  20. id++
  21. time.Sleep(1 * time.Second)
  22. es.SendEventMessage("blabla", "message", strconv.Itoa(id))
  23. }
  24. }()
  25. }

答案1

得分: 11

截至2018年12月,显然CloseNotifier已被弃用。推荐的解决方案是使用Request上下文。以下代码对我有效:

  1. done := make(chan bool)
  2. go func() {
  3. <-req.Context().Done()
  4. done <- true
  5. }()
  6. <-done
英文:

As of December 2018, apparently CloseNotifier is deprecated. The recommended solution is to use the Request Context. The following worked for me:

  1. done := make(chan bool)
  2. go func() {
  3. &lt;-req.Context().Done()
  4. done &lt;- true
  5. }()
  6. &lt;-done

答案2

得分: 6

你可以使用CloseNotifier来判断底层的HTTP连接是否关闭。例如:

  1. notify := w.(http.CloseNotifier).CloseNotify()
  2. go func() {
  3. <-notify
  4. // 连接关闭,进行清理等操作
  5. }()

希望对你有帮助。

英文:

You can use CloseNotifier which lets you know if the underlying http connection has closed. Like:

  1. notify := w.(http.CloseNotifier).CloseNotify()
  2. go func() {
  3. &lt;-notify
  4. // connection close, do cleanup, etc.
  5. }()

HTH

答案3

得分: 3

你可以检查ConsumersCount()函数:

  1. go func() {
  2. var id int
  3. for es.ConsumersCount() > 0 {
  4. id++
  5. es.SendEventMessage("blabla", "message", strconv.Itoa(id))
  6. time.Sleep(1 * time.Second)
  7. }
  8. fmt.Println("closed")
  9. }()

这种方法可能有点巧妙,但似乎可以工作。

你可能最好使用其他包或自己编写代码,这样你可以更好地控制goroutine的生命周期。你可以在.Write方法中检测到连接关闭(该包没有公开该方法)。

如果你想要的话,这里有一个使用TCP的聊天服务器示例:chat-server
还有一个配套的视频教程:tutorial

对于SSE,相同的基本模式应该适用。

英文:

You could check ConsumersCount():

  1. go func() {
  2. var id int
  3. for es.ConsumersCount() &gt; 0 {
  4. id++
  5. es.SendEventMessage(&quot;blabla&quot;, &quot;message&quot;, strconv.Itoa(id))
  6. time.Sleep(1 * time.Second)
  7. }
  8. fmt.Println(&quot;closed&quot;)
  9. }()

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.

huangapple
  • 本文由 发表于 2015年8月21日 00:27:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/32123546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定