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

Flutter应用启动后切换网络,Socket.connect为何无法正常工作?

问题解决:Flutter切换网络后Socket.connect连接失败

问题描述

使用dart:io的Socket.connect可正常连接NETWORK A中的服务IP:端口,但应用启动时处于NETWORK B,切换到NETWORK A后连接失败。

核心原因

应用启动在NETWORK B时,Dart会缓存该主机的DNS解析结果;切换到NETWORK A后,默认的Socket.connect会复用旧缓存的解析地址,而非重新发起适用于当前网络的DNS查询,导致连接失败。

解决方案

1. 强制刷新DNS解析,使用最新IP连接

手动执行DNS查询获取当前网络下的最新IP,再基于该IP建立Socket连接,绕过缓存。

代码示例:

import 'dart:io';

Future<void> connectToService(String host, int port, Duration timeout) async {
  try {
    // 手动查询当前网络下的主机IP地址
    final addresses = await InternetAddress.lookup(host);
    if (addresses.isNotEmpty) {
      // 使用查询到的第一个IP建立连接
      final socket = await Socket.connect(addresses.first, port, timeout: timeout);
      print("连接成功!");
      // 这里可以添加Socket的后续处理逻辑(如数据收发、监听断开等)
      socket.listen(
        (data) => print('收到数据: ${String.fromCharCodes(data)}'),
        onDone: () => print('连接断开'),
        onError: (err) => print('Socket错误: $err'),
      );
    } else {
      print("未找到主机对应的IP地址");
    }
  } catch (e) {
    print("连接失败: $e");
  }
}

2. 监听网络状态变化,自动重试连接

结合connectivity_plus包监听网络状态,在网络切换时自动触发重新连接逻辑,确保网络变更后及时尝试新连接。

代码示例:

import 'dart:io';
import 'package:connectivity_plus/connectivity_plus.dart';

class SocketConnector {
  final Connectivity _connectivity = Connectivity();
  StreamSubscription<ConnectivityResult>? _networkSubscription;
  late String _targetHost;
  late int _targetPort;
  late Duration _connectTimeout;
  Socket? _currentSocket;

  void initialize(String host, int port, Duration timeout) {
    _targetHost = host;
    _targetPort = port;
    _connectTimeout = timeout;
    // 监听网络状态变化
    _networkSubscription = _connectivity.onConnectivityChanged.listen((result) {
      print("网络状态变更: $result");
      _reconnect();
    });
    // 初始连接尝试
    _reconnect();
  }

  Future<void> _reconnect() async {
    // 先关闭之前的连接(如果存在)
    _currentSocket?.destroy();
    try {
      final addresses = await InternetAddress.lookup(_targetHost);
      if (addresses.isNotEmpty) {
        _currentSocket = await Socket.connect(addresses.first, _targetPort, timeout: _connectTimeout);
        print("网络切换后连接成功");
        // 处理Socket数据
        _currentSocket?.listen(
          (data) => print('收到数据: ${String.fromCharCodes(data)}'),
          onDone: () => print('连接断开'),
          onError: (err) => print('Socket错误: $err'),
        );
      }
    } catch (e) {
      print("网络切换后连接失败: $e");
    }
  }

  void dispose() {
    _networkSubscription?.cancel();
    _currentSocket?.destroy();
  }
}

3. 合理设置连接超时

确保timeout参数设置合理,避免因网络切换后连接建立耗时稍长而被误判为失败,建议设置3-10秒的超时时间。


内容的提问来源于stack exchange,提问作者eriel marimon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:00:06