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

Flutter/Dart使用mqtt_client通过MQTTS连接Azure IoT Hub报错求解决方案

核心错误原因
  • MqttServerClient 构造的第一个参数仅支持传入纯主机域名,你把/$iothub/websocket路径也填入导致域名解析失败,系统把整个带路径的字符串当作主机名查询DNS,自然找不到对应地址
  • 直接把Azure IoT Hub完整连接字符串作为主机参数传入,不符合参数格式要求
  • 如果使用WebSocket方式连接,/$iothub/websocket 是路径参数,需要单独配置,不能拼接在主机域名后
可直接运行的示例代码

首先在 pubspec.yaml 中添加依赖:

dependencies:
  mqtt_client: ^10.0.0

方式1:TCP TLS连接(端口8883,推荐无防火墙限制场景使用)

import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';

Future<void> connectAzureIoTHub() async {
  // 替换为你自己的配置
  const hubName = '<你的IoT Hub名称>';
  const deviceId = '<你的设备ID>';
  const sasToken = 'SharedAccessSignature sr=<hubname>.azure-devices.net%2Fdevices%2Ftestdevice&sig=xxxxxxx&se=过期时间戳';

  // 第一个参数仅填纯主机域名,第二个参数填设备ID(必须和实际一致)
  final client = MqttServerClient('$hubName.azure-devices.net', deviceId);

  // 基础配置
  client.port = 8883;
  client.secure = true;
  client.keepAlivePeriod = 60;
  // 临时关闭证书校验(生产环境请删除该行,配置合法证书校验)
  client.onBadCertificate = (cert) => true;

  // 构造连接消息
  final connMessage = MqttConnectMessage()
      .authenticateAs(
        // 用户名格式固定
        '$hubName.azure-devices.net/$deviceId/?api-version=2018-06-30',
        sasToken
      )
      .startClean()
      .withWillQos(MqttQos.atLeastOnce);
  client.connectionMessage = connMessage;

  try {
    print('开始连接Azure IoT Hub...');
    await client.connect();
    print('连接成功!');

    // 订阅云端下发消息的topic
    client.subscribe('devices/$deviceId/messages/devicebound/#', MqttQos.atLeastOnce);
    
    // 监听收到的消息
    client.updates?.listen((List<MqttReceivedMessage<MqttMessage>> messages) {
      for (final message in messages) {
        final payload = MqttPublishPayload.bytesToStringAsString((message.payload as MqttPublishMessage).payload.message);
        print('收到云端消息: ${message.topic}, 内容: $payload');
      }
    });

    // 示例:发送消息到IoT Hub
    final publishPayload = MqttClientPayloadBuilder();
    publishPayload.addString('{"deviceId":"$deviceId", "data":"测试数据"}');
    client.publishMessage(
      'devices/$deviceId/messages/events/',
      MqttQos.atLeastOnce,
      publishPayload.payload!
    );
    print('消息发送完成');

  } catch (e) {
    print('连接失败: $e');
    client.disconnect();
  }
}

方式2:WebSocket TLS连接(端口443,适合有防火墙限制仅开放80/443的场景)

仅需要在上述TCP连接代码基础上修改配置即可:

final client = MqttServerClient('$hubName.azure-devices.net', deviceId);
client.port = 443; // 端口改为443
client.useWebSocket = true; // 开启WebSocket
client.websocketProtocols = ['mqtt']; // 固定协议头
client.secure = true;
// 配置WebSocket路径,注意$符号要转义
client.wsUriString = 'wss://$hubName.azure-devices.net/\$iothub/websocket';

// 其余连接、收消息、发消息逻辑和TCP连接完全一致
注意事项
  • SAS令牌请提前生成,注意配置合理的过期时间,生成时sr参数必须和设备路径完全匹配
  • 生产环境请删除onBadCertificate的跳过校验逻辑,避免安全风险
  • 设备到云的消息固定发送到topic devices/<设备ID>/messages/events/,云到设备的消息固定从topic devices/<设备ID>/messages/devicebound/# 订阅

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:48:03