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

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_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:05:18