Flutter模拟器MQTT连接失败报SocketException问题求助
SocketException: Network is unreachable (errno=101) 排查方案
一、先验证基础网络连通性
- 测试模拟器自身网络:打开模拟器内置浏览器,访问任意公开网站(如百度),如果无法访问,说明模拟器网络本身异常。
- 解决方式:重启模拟器;Android模拟器可尝试在设置中重置网络,或在AVD管理器中切换网络模式为"Bridge"。
- 若MQTT Broker部署在本地主机:Android模拟器需用
10.0.2.2替代localhost/127.0.0.1访问主机服务,因为模拟器的回环地址与主机不共享。
二、检查MQTT Broker配置有效性
- 确认
MqttConstants.broker和MqttConstants.port未变更:比如Broker的IP/域名是否失效、端口是否被修改(如从1883改为8883但代码未同步)。 - 用工具测试Broker连通性:在主机上执行
telnet <broker地址> <端口>,或用MQTTX等客户端工具连接,若无法连通,说明Broker本身不可用或端口被防火墙拦截。
三、修复代码中的Client初始化问题
你的代码中mqttSubscribe方法每次调用都会重新创建client实例,覆盖全局变量,导致旧连接状态丢失、重连逻辑混乱:
// 全局已声明client,但每次订阅又重新初始化,破坏原有连接状态 client = MqttServerClient(MqttConstants.broker, MqttConstants.clientId);
优化方案:只初始化一次client实例,例如在页面initState中完成初始化:
late MqttServerClient client; @override void initState() { super.initState(); // 仅初始化一次client client = MqttServerClient(MqttConstants.broker, MqttConstants.clientId); client.port = MqttConstants.port; client.autoReconnect = true; client.logging(on: true); client.keepAlivePeriod = 60; client.pongCallback = pong; client.onDisconnected = onDisconnected; final connMess = MqttConnectMessage() .authenticateAs(MqttConstants.username, MqttConstants.password) .withClientIdentifier(MqttConstants.clientId) .withWillQos(MqttQos.atLeastOnce) .startClean(); client.connectionMessage = connMess; } // 修改订阅方法,不再重复初始化client Future<Stream<List<MqttReceivedMessage<MqttMessage>>?>? mqttSubscribe({required String topic}) async { try { // 若未连接则尝试连接 if (client.connectionStatus?.state != MqttConnectionState.connected) { await client.connect(); } if (client.connectionStatus?.state == MqttConnectionState.connected) { client.subscribe(topic, MqttQos.atMostOnce); return client.updates; } else { return null; } } on NoConnectionException catch (e) { log(e.toString()); return null; } }
四、排查权限与自动重连逻辑
- 检查AndroidManifest.xml网络权限:确保包含
<uses-permission android:name="android.permission.INTERNET" />,无权限则添加。 - 增强断开回调的重连逻辑,确认重连触发:
void onDisconnected() { print('disconnected, attempting reconnect...'); // 延迟5秒后尝试手动重连,作为自动重连的补充 Future.delayed(const Duration(seconds: 5), () async { try { await client.connect(); } catch (e) { print('reconnect failed: $e'); } }); }
内容的提问来源于stack exchange,提问作者syaf_
相关产品推荐
相关产品推荐

