Eventsource golang:如何检测客户端断开连接?

Posted

技术标签:

【中文标题】Eventsource golang:如何检测客户端断开连接?【英文标题】:Eventsource golang : how to detect client disconnection? 【发布时间】:2015-11-14 09:48:12 【问题描述】:

我正在开发基于 Twitter 标签的聊天室,其中包含服务器发送的事件,包 https://github.com/antage/eventsource

我有一个关于客户端断开连接的问题。我运行了一个 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))
        
    ()


【问题讨论】:

【参考方案1】:

您可以查看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")
    ()

有点 hacky,但它似乎工作。

您最好使用不同的包或滚动自己的包,这样您就可以更好地控制 goroutine 的生命周期。您可以在.Write 上检测到关闭的连接(此包未公开)。

如果你想要下面的 TCP 聊天服务器示例:chat-server。 还有一个视频教程:tutorial。

同样的基本模式应该适用于 SSE。

【讨论】:

感谢您的回答。我的问题是我使用的包没有提出 ConsumerCount() 函数。【参考方案2】:

您可以使用CloseNotifier 让您知道底层http 连接是否已关闭。喜欢:

notify := w.(http.CloseNotifier).CloseNotify()
go func() 
    <-notify
    // connection close, do cleanup, etc.
()

HTH

【讨论】:

【参考方案3】:

截至 2018 年 12 月,apparently CloseNotifier is deprecated。推荐的解决方案是使用Request 上下文。以下对我有用:

done := make(chan bool)
go func() 
        <-req.Context().Done()
        done <- true
()
<-done

【讨论】:

您是否有一个完整的示例适合原始问题,因为我无法让它工作?谢谢。 @anderspitman 有没有办法区分优雅的客户端断开连接和使用此方法的突然客户端断开连接? @ymerej 不是我所知道的。检测 TCP 断开连接实际上可能相当棘手。 不需要done 频道 - 只需直接使用&lt;-req.Context().Done() - 并使用selectdefault 进行非阻塞轮询。

以上是关于Eventsource golang:如何检测客户端断开连接?的主要内容,如果未能解决你的问题,请参考以下文章

每个应用程序应该只有一个 EventSource 对象吗?

通过SSE(Server-Send Event)实现服务器主动向浏览器端推送消息

服务器推送的实现—基于EventSource

所有事件的 HTML5 EventSource 侦听器?

如何使用 Windows 性能分析器查看 EventSource 创建的 ETW 事件?

Server-sent events(SSE)& EventSource 客户端使用与服务器基础实现(基于Node.js)