Flutter web_socket_channel断网重连后可收消息但无法发送问题求助
问题分析与解决方案
你的问题核心是断网重连后WebSocket能接收消息但无法发送,主要原因在于现有代码的连接管理逻辑存在缺陷:
- 每次调用
ws_connect()都会创建局部的WebSocketChannel实例,旧连接断开后未主动关闭,导致资源泄漏,可能出现新旧连接实例混淆的情况; - 未处理连接异常/关闭后的重连逻辑,也没有校验发送消息时
sink的有效性。
修复后的代码
WebSocketChannel? _wsChannel; void wsConnect() async { // 先关闭旧连接,避免资源泄漏 if (_wsChannel != null) { await _wsChannel!.sink.close(); _wsChannel = null; } try { _wsChannel = IOWebSocketChannel.connect('wss://...'); _wsChannel!.stream.listen((data) { print(data); if (data == 'hello') { // 发送前校验sink状态,确保连接有效 if (_wsChannel?.sink != null && !_wsChannel!.sink.isClosed) { _wsChannel!.sink.add(data); } } }, onError: (error) { print('WebSocket错误: $error'); // 延迟重连,避免频繁请求 Future.delayed(const Duration(seconds: 3), wsConnect); }, onDone: () { print('WebSocket连接关闭'); // 连接断开后自动重连 Future.delayed(const Duration(seconds: 3), wsConnect); }); } catch (e) { print('WebSocket连接失败: $e'); Future.delayed(const Duration(seconds: 3), wsConnect); } }
关键修复点说明
- 全局管理连接实例:用全局变量
_wsChannel保存当前有效的WebSocket连接,确保发送消息时指向的是最新的连接实例; - 主动关闭旧连接:重连前先关闭旧的
sink,释放底层资源,避免无效连接残留; - 校验sink状态:发送消息前检查
sink是否处于打开状态,避免向已失效的连接发送消息; - 自动重连逻辑:在连接错误或关闭时触发延迟重连,避免短时间内频繁发起连接请求,同时保证网络恢复后能自动重建连接。
如果问题仍然存在,建议检查服务器端是否对重复连接有特殊限制(比如同一客户端ID的旧连接未清理,导致新连接的发送被拦截),但从客户端表现来看,优先排查上述客户端逻辑问题即可。
内容的提问来源于stack exchange,提问作者Khaiyom
相关产品推荐
相关产品推荐

