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

Flutter中Socket关闭后HTTP及全局网络异常问题求助

问题分析与解决思路

从你提供的代码和报错信息来看,核心问题是Socket资源未彻底释放+网络切换后应用未同步更新网络状态,导致全局网络连接失效。以下是针对性的解决方案:


1. 彻底清理Socket相关资源

当前代码只关闭了Socket,但未取消监听的StreamSubscription(_sockStrem),这会导致资源泄漏,占用网络接口。修改sockListenCb方法:

void sockListenCb(event) async {
  String data = String.fromCharCodes(event);
  print(data);
  print('----------->>>>');

  // 1. 先取消Socket流的订阅,避免资源泄漏
  if (_sockStrem != null) {
    await _sockStrem?.cancel();
    _sockStrem = null;
  }

  // 2. 完整关闭Socket:先flush确保数据发送完成,再close
  if (_socket != null) {
    try {
      await _socket?.flush();
      await _socket?.close();
      await Future.delayed(const Duration(milliseconds: 100));
      _socket = null;
      print('回调销毁socket =>$_socket');
    } catch (e) {
      print('销毁socket出错: $e');
      _socket?.destroy();
      _socket = null;
    }
  }
  
  await FlutterIotWifi.disconnect();
  // 3. 等待网络切换完成后再进行后续操作
  await _waitForNetworkStable();
}

// 新增:等待网络连接稳定的方法
Future<void> _waitForNetworkStable() async {
  // 循环检查网络状态,直到能正常访问目标服务器
  for (int i = 0; i < 10; i++) {
    await Future.delayed(const Duration(seconds: 1));
    try {
      // 验证是否能解析目标域名(替代ping)
      final addr = await InternetAddress.lookup('qdevice.duoqin.com');
      if (addr.isNotEmpty && addr[0].rawAddress.isNotEmpty) {
        return;
      }
    } catch (_) {}
  }
}

同时,在Socket错误处理中也要同步清理资源:

void errorHandler(error) {
  print('Socket监听错误: $error');
  _sockStrem?.cancel();
  _sockStrem = null;
  _socket?.close();
  _socket = null;
}

2. 避免复用全局HTTP客户端

全局http.Client会缓存旧的网络连接,网络切换后需要重新创建实例,不要复用:

// 每次HTTP请求都创建新的Client,用完即关闭
Future<void> sendHttpRequest() async {
  final client = http.Client();
  try {
    final response = await client.get(
      Uri.parse('https://qdevice.duoqin.com/device/action?culture=en-US')
    );
    // 处理响应逻辑
  } catch (e) {
    print('HTTP请求失败: $e');
  } finally {
    client.close();
  }
}

3. 修正WiFi连接判断逻辑

当前用Future.delayed(8秒)判断连接状态非常不可靠,改用WiFi状态监听:

void _connectWifi(String ssid, String password, Function(bool) callback) async { 
  if (!await WiFiForIoTPlugin.isEnabled()) {  
    await WiFiForIoTPlugin.setEnabled(true);
  }

  // 监听WiFi连接状态变化
  final subscription = WiFiForIoTPlugin.onWiFiConnectionChanged().listen((event) async {
    if (event.isConnected && event.ssid == ssid) {
      await subscription.cancel();
      callback(true);
    }
  });

  // 发起连接
  await FlutterIotWifi.connect(ssid, password, prefix: false);

  // 设置超时:10秒内未连接上则返回失败
  await Future.delayed(const Duration(seconds: 10), () async {
    if (!subscription.isPaused) {
      await subscription.cancel();
      callback(false);
    }
  });
}

4. 监听系统网络切换事件

用connectivity_plus监听网络状态变化,在切换到正常WiFi后重置网络相关资源:

// 在initState中添加监听
@override
void initState() {
  super.initState();
  Connectivity().onConnectivityChanged.listen((result) {
    if (result == ConnectivityResult.wifi) {
      // 网络切换到WiFi,可在此重置HTTP客户端或清理旧连接
      _socket = null;
      _sockStrem = null;
    }
  });
}

内容的提问来源于stack exchange,提问作者李大龙

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:35:23