Echo中收不到客户端断连通知,因HTTP/1.1和WebSocket连接关闭时TCP可能静默终止,c.Request().Context().Done()不响应拔网线等行为;Go 1.8+已移除http.CloseNotifier,正确方式是结合SetReadDeadline探测空闲连接,但仅适用于HTTP handler;WebSocket需用gorilla/websocket独立注册路由,通过ReadMessage()返回*websocket.CloseError或io.EOF捕获断连。

为什么Echo里收不到客户端断连通知
因为HTTP/1.1和WebSocket连接关闭时,底层TCP连接可能静默终止,echo.Context不会自动感知;Echo的c.Request().Context().Done()只在请求超时或服务端主动取消时触发,不响应客户端拔网线、关浏览器标签等行为。
用http.CloseNotifier已失效,该用什么
Go 1.8+ 已移除http.CloseNotifier接口,不能再依赖它。正确方式是监听http.Request.Context().Done()并配合net.Conn.SetReadDeadline()探测空闲连接状态——但注意:这仅对HTTP handler有效,对WebSocket无效(见后文)。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 必须在handler开头就调用
c.Request().Context().Done()监听,不能延迟注册 - 需手动启用连接读写 deadline:
c.Request().Context().Value(http.ServerContextKey).(*http.Server)拿到*http.Server,再从c.Request().RemoteAddr获取net.Conn(需类型断言) - 若使用
echo.HTTPErrorHandler,错误处理函数内c.Request().Context()可能已被取消,无法再读取body或写响应
WebSocket场景下客户端断连怎么捕获
如果你用gorilla/websocket在Echo里挂WebSocket路由,这是危险操作——Echo中间件会提前写Header,导致upgrader.Upgrade() panic 并静默失败。此时你根本收不到连接,更别说断连。
- 必须剥离Echo路由,改用
http.ServeMux或http.HandleFunc单独注册/ws路径 - 在WebSocket handler里,用
conn.SetPingHandler()+conn.SetPongHandler()配合定时心跳,客户端断开后conn.ReadMessage()会立即返回*websocket.CloseError或io.EOF - 别依赖
defer conn.Close()清理资源——要显式监听conn.ReadMessage()返回错误,并在case 分支里做兜底关闭
真正可靠的断连探测只有一种方式
客户端主动断开没有“事件”,只有“后续操作失败”。最稳的做法不是等通知,而是每次发送前检查连接状态,每次接收后判断错误类型。
- HTTP流式响应(如SSE):用
hijack拿到net.Conn,定期Write()一个空字节并检查err是否为broken pipe或connection reset - WebSocket:必须实现应用层心跳(ping/pong),且服务端
SetWriteDeadline()要短于客户端ping间隔,否则断连后要等几十秒才感知 - 别把
context.CancelFunc当断连信号——它只反映服务端逻辑取消,跟TCP链路无关


















