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

Flutter web_socket_channel断网重连后可收消息但无法发送问题求助

问题分析与解决方案

你的问题核心是断网重连后WebSocket能接收消息但无法发送,主要原因在于现有代码的连接管理逻辑存在缺陷:

  1. 每次调用ws_connect()都会创建局部的WebSocketChannel实例,旧连接断开后未主动关闭,导致资源泄漏,可能出现新旧连接实例混淆的情况;
  2. 未处理连接异常/关闭后的重连逻辑,也没有校验发送消息时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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:45:13