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
相关产品推荐
相关产品推荐

