Flutter Web使用mqtt_client连接Mosquitto报websocket has erred错误
Flutter Web mqtt_client连接Mosquitto WebSocket报错解决方案
错误原因
代码存在以下几个问题导致连接失败:
MqttBrowserClient构造参数禁止携带ws:///wss://协议头,协议由客户端内部根据运行环境自动拼接,手动添加会导致地址解析错误- 主机名大小写不匹配,测试用的主机名是
becartpi,代码中写为becArtPi,部分系统对主机名大小写敏感会导致解析失败 - 缺少Mosquitto WebSocket默认路径后缀
/mqtt,MQTT Explorer连接时会自动补全该默认路径,代码中未补全会导致请求404触发Socket断开 - 代码中使用了
dart:io库的exit(-1)方法,Flutter Web环境不支持该API,会触发额外运行时错误 - 发布消息时
MqttClientPayloadBuilder未写入任何内容就强制调用payload!,会触发空指针异常
修复步骤
- 先确认Mosquitto服务配置正确,打开
mosquitto.conf检查WebSocket相关配置:
# 开启8080端口WebSocket监听 listener 8080 0.0.0.0 protocol websockets # 未自定义路径时默认路径为/mqtt,如果你自定义了路径要同步修改代码里的路径
- 替换原代码为修正后的版本:
// 去掉协议头,主机名全小写,加上默认路径/mqtt final client = MqttBrowserClient('becartpi/mqtt', 'flutter'); void onPRessMQTTTest() async { client.onDisconnected = onDisconnected; client.onConnected = onConnected; client.onSubscribed = onSubscribed; client.logging(on: true); client.port = 8080; client.keepAlivePeriod = 20; final connMess = MqttConnectMessage() .withClientIdentifier('flutter') .startClean() .withWillQos(MqttQos.atLeastOnce); // 如果你的Mosquitto开启了用户名密码验证,添加下面这行 // connMess.authenticateAs('你的用户名', '你的密码'); print('EXAMPLE::Mosquitto client connecting....'); client.connectionMessage = connMess; try { await client.connect(); } on NoConnectionException catch (e) { print('EXAMPLE::client exception - $e'); client.disconnect(); } on SocketException catch (e) { print('EXAMPLE::socket exception - $e'); client.disconnect(); } catch (e) { print('MQTT Connection Error: $e'); client.disconnect(); return; } client.updates!.listen((List<MqttReceivedMessage<MqttMessage?>>? c) { final recMess = c![0].payload as MqttPublishMessage; final pt = MqttPublishPayload.bytesToStringAsString(recMess.payload.message); print('EXAMPLE::Change notification:: topic is <${c[0].topic}>, payload is <-- $pt -->'); print(''); }); if (client.connectionStatus!.state == MqttConnectionState.connected) { print('EXAMPLE::Mosquitto client connected'); } else { print('EXAMPLE::ERROR Mosquitto client connection failed - disconnecting, status is ${client.connectionStatus}'); client.disconnect(); // 移除不支持的exit方法,改为直接返回 return; } const pubTopic = 'Dart/Mqtt_client/testtopic'; final builder = MqttClientPayloadBuilder(); // 给payload添加内容,避免空指针 builder.addString('测试消息内容'); client.publishMessage(pubTopic, MqttQos.exactlyOnce, builder.payload!); } void onDisconnected() {} void onConnected() { print('EXAMPLE::OnConnected client callback - Client connection was successful'); } void onSubscribed(String topic) {}
- 调试时如果遇到跨域报错,可临时打开浏览器禁用安全模式测试,生产环境需要在Mosquitto配置中添加跨域允许规则。
内容的提问来源于stack exchange,提问作者Duncan Pullen
相关产品推荐
相关产品推荐

