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/,云到设备的消息固定从topicdevices/<设备ID>/messages/devicebound/#订阅
内容的提问来源于stack exchange,提问作者aknoefel
相关产品推荐
相关产品推荐

