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

Flutter MQTT发布消息报错:连接需处于Connected状态

MQTT发布消息报错问题排查与解决

问题描述

作为Flutter/Dart新手,使用mqtt-client库发布MQTT消息时,持续触发以下异常:

Unhandled Exception: mqtt-client::ConnectionException: The connection must be in the Connected state in order to perform this operation

已确认能成功连接MQTT服务器,可正常订阅主题并接收消息,但点击按钮调用publish方法时必现该异常。尝试在publish内调用带await的connect()可成功发布,但会建立第二个连接。疑问:是否必须使用WebSocket连接?

核心原因

  1. 发布时客户端实际连接状态异常:尽管订阅功能正常,_notifier标记的连接状态为已连接,但客户端内部的实际连接状态可能已断开(如keepalive超时、网络波动导致隐式断开),且未同步到_notifier。
  2. publish方法无状态校验:直接调用client.publishMessage,未提前确认客户端是否处于有效连接状态。
  3. 与WebSocket无关:当前使用TCP端口1883连接正常,问题并非连接方式导致。

解决方案

1. 发布前强制校验连接状态

修改publish方法,先检查客户端实际连接状态,仅在状态有效时执行发布:

void publish(String message) async {
  // 校验客户端实际连接状态
  if (client.connectionStatus?.state != MqttConnectionState.connected) {
    print("客户端未处于连接状态,无法发布消息");
    return;
  }
  final MqttClientPayloadBuilder builder = MqttClientPayloadBuilder();
  builder.addString(message);
  client.publishMessage(_topic, MqttQos.exactlyOnce, builder.payload!);
}

2. 修复状态同步逻辑

确保_notifier的连接状态与客户端实际状态完全同步,可添加对client.connectionStatus的监听:
在InitMqttClient方法中添加:

client.onSubscribed = onSubscribed;
// 新增:监听连接状态变化
client.connectionStatus?.listen((status) {
  if (status.state == MqttConnectionState.connected) {
    _notifier.SetConnectionState(ConnectionState.connected);
    _notifier.SetBtnConnectionActivity(BtnConnectionActivity.disconnect);
  } else if (status.state == MqttConnectionState.disconnected) {
    _notifier.SetConnectionState(ConnectionState.disconnected);
    _notifier.SetBtnConnectionActivity(BtnConnectionActivity.connect);
  }
});
client.keepAlivePeriod = 20;

同时移除connect方法中手动设置状态的代码,避免重复更新:

void connect() async {
  assert(client != null);
  try {
    if(_notifier.GetCurrentConnectionState == ConnectionState.connected)
    {
      client.disconnect();
    }
    else
    {
      await client.connect();
      // 移除手动设置状态的代码,交由connectionStatus监听处理
      subscribe();
    }
  } catch (e) {
    _notifier.SetConnectionState(ConnectionState.disconnected);
    print('Exception: $e');
    client.disconnect();
  }
}

3. 断开时自动重连(可选)

若需提升稳定性,可在onDisconnected中添加重连逻辑:

void onDisconnected() {
  _notifier.SetConnectionState(ConnectionState.disconnected);
  _notifier.SetBtnConnectionActivity(BtnConnectionActivity.connect);
  // 可选:延迟重连
  Future.delayed(const Duration(seconds: 3), () {
    if (_notifier.GetCurrentConnectionState != ConnectionState.connected) {
      connect();
    }
  });
}

关键说明

  • 无需切换到WebSocket:当前TCP连接方式有效,问题与连接协议无关。
  • 避免重复连接:不要在publish中直接调用connect(),而是先校验状态,断开时触发重连逻辑,复用已有客户端实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 10:42:46