You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gorilla WebSocket超时为何直接关闭连接而非调用CloseHandler方法?

关于gorilla/websocket连接超时未触发SetCloseHandler的问题分析

我来帮你拆解这个问题,其实核心是gorilla/websocket里SetCloseHandler的触发条件和你遇到的超时场景不匹配,咱们一步步说清楚:

1. 先理解1006错误的本质

你看到的websocket: close 1006 (abnormal closure): unexpected EOF,是TCP层面的异常断开,不是WebSocket协议规范里的「正常关闭流程」。1006是WebSocket定义的「异常关闭」码,用于表示连接没有通过交换Close帧就直接断开了——比如超时、网络中断、对方进程崩溃等场景。

2. SetCloseHandler的触发条件

SetCloseHandler只负责处理对方发送了合法WebSocket Close帧的情况:当连接的另一端主动发送符合规范的Close帧(带1000、1001这类正常关闭码),gorilla/websocket会先调用你设置的CloseHandler,再关闭连接。

而超时导致的断开,属于底层TCP连接直接终止,没有经过WebSocket的Close帧交换流程,所以这个handler根本不会被触发。

3. 该怎么处理这种超时/异常断开?

要捕获这类场景,你需要用到这两种方式:

  • 设置SetErrorHandler:所有连接层面的异常错误(包括超时、EOF、TCP断开)都会触发这个handler,你可以在这里判断错误类型并执行你的逻辑:
ws.SetErrorHandler(func(err error) {
    // 判断是否是异常关闭类错误
    if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
        fmt.Println("socket close")
    }
})
  • 在读写循环中捕获错误:因为gorilla/websocket的读写操作(ReadMessage/WriteMessage)会在连接异常断开时返回错误,你可以在业务的读写循环里直接处理:
for {
    _, msg, err := ws.ReadMessage()
    if err != nil {
        fmt.Println("socket close")
        // 这里可以做连接重连、资源清理等操作
        break
    }
    // 处理收到的消息msg
}

简单总结:SetCloseHandler管的是「礼貌的WebSocket挥手」,而超时这类「不打招呼的断开」属于异常错误,得用ErrorHandler或者读写循环的错误捕获来处理~

内容的提问来源于stack exchange,提问作者Holdno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:55:44