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
相关产品推荐
相关产品推荐

