Python服务端Flask-SocketIO能否获取socket断开连接的原因?
Flask SocketIO 获取断开原因实现方案
方案1:原生支持(适配Flask-SocketIO v5.0及以上版本)
新版Flask-SocketIO已经支持disconnect回调传入原因参数,只需给回调函数增加对应入参即可直接获取:
@socketio.on('disconnect') def on_disconnect(reason): print(f'Socket已断开,断开原因:{reason}')
获取到的原因值和Socket.IO官方定义的断开原因完全对应,常见取值包括:
client namespace disconnect:客户端主动触发断开server namespace disconnect:服务端主动调用断开接口ping timeout:心跳超时未收到客户端响应transport close:传输层连接异常关闭transport error:传输层出现报错
方案2:旧版本兼容替代方案
如果使用的是v4及以下不支持原生传参的版本,可以通过自定义事件+会话存储的方式实现原因采集:
步骤1:前端主动断开前上报原因
前端在所有主动触发断开的逻辑前,先发送自定义事件携带断开原因:
// 前端主动断开前的逻辑 socket.emit('pre_disconnect', { reason: '用户主动退出登录' }) socket.disconnect()
步骤2:后端存储并读取断开原因
后端接收自定义事件后把原因存到Socket会话中,断开时读取即可:
from flask_socketio import session @socketio.on('pre_disconnect') def handle_pre_disconnect(data): # 把前端上报的原因存入当前Socket的专属会话 session['custom_disconnect_reason'] = data.get('reason', '前端未指定原因') @socketio.on('disconnect') def on_disconnect(): # 优先读取自定义上报的原因,未取到则判定为异常断开 reason = session.get('custom_disconnect_reason', '网络异常/心跳超时导致断开') # 可在此处把原因、socket ID、用户标识等信息统一上报到日志系统 print(f'Socket已断开,断开原因:{reason}')
异常断开补充优化
对于前端没机会上报原因的异常断开场景,可通过心跳打点辅助判断:给每个Socket连接记录最后一次心跳接收时间,断开时如果当前时间和最后心跳时间的差值超过你设置的心跳超时阈值,即可明确判定为心跳超时导致的断开。
多服务部署场景下,建议把断开原因、连接时长、用户ID、Socket ID、所属服务标识等字段统一聚合到日志平台,方便跨服务排查问题。
内容的提问来源于stack exchange,提问作者seanlermsss
相关产品推荐
相关产品推荐

