MQTT物联网通信实战:Windows搭建+Java集成+ESP32开发
1. 这不是“又一个MQTT教程”而是一份能直接上手的物联网通信实战笔记我做物联网项目快八年了从最早用ArduinoESP8266硬啃AT指令到后来带团队落地智慧农业、工业设备远程监控、楼宇能源管理系统MQTT几乎贯穿了所有项目的数据通路。它不像HTTP那样人人熟悉也不像TCP那样需要自己处理连接状态和重传逻辑但它恰恰在“轻量”和“可靠”之间找到了那个最刁钻的平衡点——设备资源有限、网络不稳定、消息必须送达、开发周期又卡得死紧。这正是标题里“快速开发与实践”六个字的真实分量不是教你背协议字段而是让你今天下午搭好Broker晚上就能让温湿度传感器把数据推到手机App上。核心关键词就三个MQTT、物联网协议、快速开发它们分别对应协议本质、应用场域和落地节奏。如果你正被这些事困扰——比如刚买了ESP32开发板却卡在连不上服务器、写Java后台时发现Paho客户端配置一堆参数无从下手、或者现场调试485设备时搞不清“MQTT发指令”到底要转换成什么格式——那这篇就是为你写的。它不假设你懂TCP三次握手也不要求你先读完30页协议文档它默认你手边有台Windows电脑、一个USB转TTL模块、一块带WiFi的MCU以及一个迫切想让设备说话的念头。下面所有内容都来自我踩过的坑、调通的代码、写烂的配置文件以及客户凌晨三点打来电话说“数据断了”的真实压力。2. 为什么是MQTT不是HTTP、CoAP也不是自定义TCP协议2.1 协议选型背后的现实博弈资源、网络、业务三重约束选协议从来不是技术洁癖而是资源、网络、业务三张考卷的综合得分。我拿三个真实场景对比一下智慧水表项目部署在地下井盖里NB-IoT模组供电靠电池续航要求5年。HTTP每次请求都要建连接、传Header、等响应一次上报耗电约12mA·s而MQTT复用长连接Publish一条16字节温度数据仅需2.3mA·s光这一项就让电池寿命从18个月拉到5年以上。这里MQTT的“轻量”不是形容词是毫安秒级的实打实计算。工厂产线PLC监控车间WiFi信号穿墙后RSSI常在-75dBm徘徊丢包率12%。HTTP超时重试机制简单粗暴一次POST失败就得整个重发MQTT的QoS分级0/1/2让关键报警消息走QoS1至少一次送达普通状态数据走QoS0最多一次配合Broker的持久化存储断网期间的消息不会丢失恢复后自动补发。这不是“理论上可靠”而是客户指着屏幕说“刚才停机那3分钟的数据你们真有”。多厂商设备接入平台甲方采购了A厂的电表、B厂的烟感、C厂的门禁各设备SDK五花八门。如果每个都写HTTP适配层半年内维护成本会爆炸。MQTT的Topic设计天然解耦factory/line1/machineA/temperature、building/zone3/fire/smoke、gate/entrance1/status设备只管往Topic发数据平台只订阅Topic收数据中间Broker像交通指挥中心彻底隔离设备与业务系统。这种“发布-订阅”模型让新增一个设备类型往往只需改一行Topic配置而不是重写一套通信模块。提示别被“MQTT是发布订阅协议”这句话带偏。它的核心价值不在模式新颖而在用极简的二进制报文CONNECT报文最小仅2字节和精巧的状态机Clean Session、Will Message等把物联网场景里最头疼的“弱网保活”“断线续传”“多端同步”问题封装成了几行API调用。这才是“快速开发”的底层支撑。2.2 MQTT vs 其他协议一张表看清取舍逻辑对比维度MQTTHTTP/HTTPSCoAP自定义TCP协议连接模型永久TCP连接可心跳保活短连接每次请求新建UDP连接无连接靠重传长连接或短连接自定义报文开销最小2字节PINGREQHeader至少100字节含Host/UA等最小4字节CoAP Header完全自定义通常20字节QoS保障内置QoS0/1/2三级语义无内置重传依赖应用层实现QoS类比MQTT但无Session概念全靠自己实现ACK/重传逻辑广播能力Topic支持通配符订阅、#无原生广播需轮询或Webhook支持组播但实际部署复杂需自行实现组播或遍历发送开发效率主流语言均有成熟ClientPaho/EMQX SDK标准库支持好但物联网场景需额外处理Token/SSL嵌入式友好但Java/Python生态弱从Socket写起序列化/加密全自研适用场景设备→云、云→设备双向通信弱网环境设备主动上报如固件升级、Web管理界面资源极度受限设备64KB RAM极特殊需求如实时音视频流这张表里最关键的差异点其实是开发者的认知负荷。HTTP你得自己处理连接池、超时、重试、证书验证CoAP在Java里找一个稳定SDK可能要花两天而MQTT你在Windows上双击安装MosquittoJava里加两行Paho依赖设备端用Arduino PubSubClient库三端就能跑通一条消息链路。所谓“快速开发”本质是把90%的通用问题交给协议栈让你聚焦在temperature 40℃这个业务判断上而不是纠结于TCP窗口大小怎么调。2.3 MQTT不是银弹哪些场景它会掉链子再好的工具也有边界。我见过太多项目因为没看清这点后期疯狂返工高频率实时控制比如无人机姿态控制要求10ms级指令响应。MQTT的Broker转发、QoS确认流程会引入20-50ms抖动此时该用WebSocket直连或专用实时协议如ROS2 DDS。曾有个客户坚持用MQTT控制AGV小车转向结果急停延迟导致撞墙最后换成了UDP自定义校验。超大文件传输MQTT单条消息默认限制128MBMosquitto配置可调但实际中超过1MB就会显著增加内存压力和丢包风险。固件升级包动辄几十MB正确做法是MQTT只传升级URL和MD5设备用HTTP GET下载完成后发MQTT消息通知升级完成。强安全审计要求场景金融、电力行业要求通信全程可追溯、操作留痕、密钥硬件隔离。MQTT的TLS加密虽可用但密钥管理、证书吊销、操作日志等需额外构建不如直接采用国密SM4SM2的专用物联网安全协议栈。注意MQTT的“轻量”是相对的。当你把QoS2用满、开启Retain、大量使用Last Will、Topic层级过深如a/b/c/d/e/f/g/h/i/j/kBroker内存占用会指数级增长。我们线上集群曾因Topic设计不当单个Broker内存飙到16GB最后砍掉冗余层级限制Topic长度才解决。协议简单不代表滥用无代价。3. Windows环境下零门槛搭建MQTT服务从安装到验证一步到位3.1 为什么首选Mosquitto而非EMQX或RabbitMQ新手常纠结选哪个Broker。我的答案很直接Windows开发阶段只用Mosquitto。理由非常务实安装即用官网提供Windows Installer.exe双击下一步服务自动注册无需配置Java环境、Erlang虚拟机或Docker。对比EMQX要装Erlang、RabbitMQ要装ErlangOpenSSLMosquitto省下至少2小时环境折腾时间。命令行友好mosquitto_sub和mosquitto_pub两个命令覆盖90%调试场景。你想测试订阅mosquitto_sub -h 127.0.0.1 -t test回车就行想模拟设备发消息mosquitto_pub -h 127.0.0.1 -t sensor/temp -m 25.3。没有Web界面干扰专注协议本身。配置极简默认配置文件mosquitto.conf只有20行有效配置关键参数就3个listener 1883端口、allow_anonymous true是否允许游客、persistence true是否保存离线消息。改错一个参数重启服务立刻生效不像EMQX改个ACL要重启整个集群。当然生产环境我会切EMQX——它的Dashboard、规则引擎、插件生态确实强大。但开发初期过度设计是最大陷阱。就像学开车先练好油离配合再研究涡轮增压原理。3.2 手把手安装MosquittoWindows 10/11步骤1下载安装包访问Mosquitto官方下载页mosquitto.org/downloads找到Windows分类下载最新版mosquitto-2.0.x-install-windows-x64.exe注意选x64别下错x86。截至2024年2.0.x是稳定主力版本1.6.x已停止维护。步骤2静默安装关键技巧双击运行安装包出现向导时第一页勾选“I accept the agreement” → Next第二页选择安装路径强烈建议用默认路径C:\Program Files\mosquitto\。很多教程教改路径结果后续命令行找不到mosquitto.exe纯属给自己挖坑。第三页“Additional Tasks”中务必勾选“Install as Windows Service”安装为Windows服务。这样开机自动启动不用每次手动运行mosquitto.exe。第四页点击“Install”等待进度条完成。步骤3验证安装成功打开命令提示符CMD输入mosquitto -v如果返回类似mosquitto version 2.0.15说明命令已加入PATH环境变量安装成功。若提示“不是内部或外部命令”请手动添加路径右键“此电脑”→属性→高级系统设置→环境变量→系统变量→Path→编辑→新建→粘贴C:\Program Files\mosquitto\→确定。步骤4启动服务并检查端口以管理员身份运行CMD右键CMD图标→以管理员身份运行执行net start mosquitto看到“Mosquitto service was started successfully.”即启动成功。再执行netstat -ano | findstr :1883应看到类似TCP 0.0.0.0:1883 0.0.0.0:0 LISTENING 1234的输出其中1234是Mosquitto进程PID。这证明1883端口已被监听。实操心得Windows防火墙常拦截1883端口如果netstat显示LISTENING但外部设备连不上立即检查防火墙控制面板→Windows Defender防火墙→高级设置→入站规则→新建规则→端口→TCP 1883→允许连接→命名“MQTT”。这步我帮客户远程处理过37次90%的“连不上”问题根源在此。3.3 用命令行完成首次通信三步验证闭环现在Broker已就位我们用最原始的方式跑通第一条消息建立完整信心第一步开一个CMD窗口订阅主题mosquitto_sub -h 127.0.0.1 -t test/topic -v参数说明-h指定Broker地址本地用127.0.0.1-t是Topic主题名-v表示显示Topic名消息内容。执行后窗口会阻塞等待消息光标闪烁不动——这是正常现象。第二步另开一个CMD窗口发布消息mosquitto_pub -h 127.0.0.1 -t test/topic -m Hello from Windows!-m后跟消息内容字符串。回车后第一个窗口立刻打印test/topic Hello from Windows!第三步验证QoS与Retain在订阅窗口按CtrlC退出再执行mosquitto_sub -h 127.0.0.1 -t test/retain -q 1 -v-q 1指定QoS等级为1至少一次。然后在发布窗口执行mosquitto_pub -h 127.0.0.1 -t test/retain -m Retained message -r-r参数表示设置Retain标志。此时即使订阅者离线Broker也会保存最后一条Retain消息。你关闭订阅窗口再重新运行mosquitto_sub...依然能立刻收到Retained message。注意mosquitto_sub默认QoS0mosquitto_pub默认QoS0。QoS1/2需显式指定-q 1或-q 2否则看似成功实则消息可能丢失。我见过太多人用默认QoS0调试报警消息结果网络抖动时关键告警没收到最后发现是QoS没设对。4. Java快速开发框架实战Spring Boot集成Paho Client4.1 为什么Spring Boot是Java物联网后台的最优解Java生态里MQTT Client库不少Paho、Vert.x MQTT、Eclipse Milo。但做物联网后台我只推Spring Boot Paho组合原因很实在Paho是Eclipse基金会官方库更新活跃2024年仍维护API稳定文档齐全。不像某些小众库GitHub Star少、Issue没人回、连Android兼容性都没测过。Spring Boot的自动配置能力能把MQTT连接池、重连策略、线程管理这些脏活封装成几个注解。你不用写ExecutorService管理回调线程不用手动处理MqttException的各种错误码Spring Boot Starter for MQTTspring-integration-mqtt帮你兜底。与Spring生态无缝融合MQTT收到的消息可以直接注入到Service里做业务处理设备状态变更能用EventListener监听事件甚至结合Spring Security给不同Topic设置权限。这种“协议归协议业务归业务”的解耦让代码可读性提升3倍。举个真实例子我们做充电桩监控平台MQTT接收charger/001/status消息Spring Boot自动解析JSON存入MySQL同时触发Scheduled任务检查充电超时。整套流程200行代码搞定如果手写SocketJSON解析保守估计要800行且健壮性差一大截。4.2 Maven依赖与基础配置在Spring Boot项目的pom.xml中添加dependencies !-- Spring Boot Web提供REST API -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring Integration MQTT核心 -- dependency groupIdorg.springframework.integration/groupId artifactIdspring-integration-mqtt/artifactId /dependency !-- Paho MQTT Client底层驱动 -- dependency groupIdorg.eclipse.paho/groupId artifactIdorg.eclipse.paho.client.mqttv3/artifactId version1.2.5/version /dependency /dependenciesapplication.yml配置Broker连接spring: mqtt: # Broker地址格式tcp://host:port url: tcp://127.0.0.1:1883 # 客户端ID必须全局唯一建议用服务名机器IP client-id: springboot-backend-${random.value} # 用户名密码若Broker启用了认证 username: admin password: password123 # 连接超时毫秒 connection-timeout: 30000 # 心跳间隔秒 keep-alive-interval: 60 # 是否自动重连 automatic-reconnect: true提示client-id不能重复同一ID的客户端二次连接Broker会踢掉前一个。生产环境建议用spring.application.nameserver.port生成唯一ID避免集群部署时冲突。random.value是Spring Boot内置占位符每次启动生成随机字符串适合开发环境。4.3 编写MQTT消息接收器从Topic到业务对象创建一个MqttMessageHandler类处理设备上报数据Component public class MqttMessageHandler { // 订阅Topic列表支持通配符 private static final String[] TOPICS {sensor//temperature, device//status}; Autowired private MqttMessageChannel mqttMessageChannel; PostConstruct public void init() { // 启动时订阅Topic Arrays.stream(TOPICS).forEach(topic - { try { mqttMessageChannel.subscribe(topic, this::handleMessage); System.out.println(Subscribed to topic: topic); } catch (Exception e) { System.err.println(Failed to subscribe to topic : e.getMessage()); } }); } /** * 处理MQTT消息的核心方法 * param topic 消息Topic * param payload 消息负载byte[] */ private void handleMessage(String topic, byte[] payload) { try { // 将byte[]转为String再解析JSON String content new String(payload, StandardCharsets.UTF_8); System.out.println(Received on topic : content); // 根据Topic动态路由 if (topic.startsWith(sensor/)) { handleSensorData(topic, content); } else if (topic.startsWith(device/)) { handleDeviceStatus(topic, content); } } catch (Exception e) { System.err.println(Error handling message: e.getMessage()); } } private void handleSensorData(String topic, String json) { // 示例解析温湿度JSON {temp:25.3,humi:60.1,ts:1712345678} try { JSONObject obj new JSONObject(json); double temp obj.getDouble(temp); String deviceId topic.split(/)[1]; // 从sensor/001/temperature提取001 // 业务逻辑存入数据库、触发告警等 System.out.println(Device deviceId temperature: temp); } catch (JSONException e) { System.err.println(Invalid sensor JSON: json); } } private void handleDeviceStatus(String topic, String json) { // 处理设备状态变更 System.out.println(Device status update: json); } }关键点解析PostConstruct确保Spring容器初始化后自动订阅避免手动调用。topic.split(/)[1]是典型的Topic解析技巧。MQTT Topic设计成sensor/{deviceId}/temperature就能通过分割提取设备ID无需额外字段。JSONObject用的是org.json库Spring Boot默认包含比Jackson更轻量适合高频解析。4.4 发送MQTT指令给485设备发指令的完整链路这才是标题里“mqtt如何给485设备发指令”的核心。485设备本身不理解MQTT需要一个协议转换网关作为桥梁。典型架构MQTT Broker ←→ 网关Linux/ARM ←→ 485总线 ←→ 设备。网关端Java代码Spring Boot实现指令下发Service public class MqttCommandService { Autowired private MqttAsyncClient mqttClient; // Paho异步客户端 Autowired private SerialPortManager serialPortManager; // 485串口管理器 /** * 通过MQTT下发指令到485设备 * param deviceId 设备ID对应485地址 * param command 指令类型如read_temp, set_power_on * param params 指令参数JSON字符串 */ public void sendCommandTo485(String deviceId, String command, String params) { try { // 步骤1构造485协议帧以Modbus RTU为例 byte[] modbusFrame buildModbusFrame(deviceId, command, params); // 步骤2通过串口发送 serialPortManager.write(modbusFrame); // 步骤3发布MQTT反馈消息 String responseTopic gateway/485/ deviceId /response; String responsePayload {\status\:\sent\,\command\:\ command \}; mqttClient.publish(responseTopic, new MqttMessage(responsePayload.getBytes())); } catch (Exception e) { System.err.println(Failed to send command to device deviceId : e.getMessage()); } } private byte[] buildModbusFrame(String deviceId, String command, String params) { // Modbus RTU帧结构[Address][Function][Data][CRC] int address Integer.parseInt(deviceId); // 485设备地址如01 byte[] frame new byte[8]; frame[0] (byte) address; // 设备地址 // 根据command映射功能码 switch (command) { case read_temp: frame[1] 0x03; // 功能码03读保持寄存器 frame[2] 0x00; frame[3] 0x00; // 起始地址0x0000 frame[4] 0x00; frame[5] 0x01; // 读1个寄存器 break; case set_power_on: frame[1] 0x06; // 功能码06写单个寄存器 frame[2] 0x00; frame[3] 0x01; // 地址0x0001 frame[4] 0xFF; frame[5] 0x00; // 数据0xFF00开 break; } // 计算CRC16简化版实际用标准CRC16-MODBUS short crc calculateCRC16(frame, 0, 6); frame[6] (byte) (crc 0xFF); frame[7] (byte) ((crc 8) 0xFF); return frame; } private short calculateCRC16(byte[] data, int offset, int length) { // 实际项目用Apache Commons Codec的CRC16-MODBUS实现 return 0x1234; // 占位符 } }前端调用示例REST APIRestController public class CommandController { Autowired private MqttCommandService commandService; PostMapping(/api/command) public ResponseEntityString sendCommand(RequestBody CommandRequest request) { commandService.sendCommandTo485( request.getDeviceId(), request.getCommand(), request.getParams() ); return ResponseEntity.ok(Command sent); } }请求体JSON{ deviceId: 01, command: read_temp, params: {} }实操心得485指令下发最易出错的是时序控制。Modbus RTU要求帧与帧之间有3.5字符间隔T1.5否则设备无法识别。网关代码里必须用Thread.sleep()或硬件定时器保证间隔我吃过亏没加延时设备返回乱码查了两天才发现是时序问题。另外serialPortManager要用RXTX或jSSC库千万别用Java原生SerialPort已废弃且Windows兼容性差。5. 设备端开发ESP32Arduino实现MQTT稳定连接5.1 为什么选ESP32性能、成本、生态的黄金三角STM32、nRF52、ESP8266都做过最终锁定ESP32理由很朴素双核CPUWi-FiBLE主频160-240MHz足够跑FreeRTOSMQTT传感器采集不用外挂Wi-Fi模组BOM成本直降30%。对比ESP8266单核80MHz跑QoS1SSL加密时经常看门狗复位。Arduino IDE完美支持ESP32板卡管理器一键安装PubSubClient库开箱即用。不用折腾VS CodePlatformIO老工程师用惯的Arduino IDE就能干活。低功耗模式真可用深度睡眠电流10μA配合定时唤醒MQTT上报电池供电传感器轻松撑1年。STM32虽然也低功耗但Wi-Fi驱动功耗优化远不如ESP-IDF原生支持。我们一个土壤墒情监测项目用ESP32-WROOM-32外接SHT30温湿度PMS5003颗粒物传感器每天上报3次CR123A锂电池用14个月客户验收时当场拆电池验证。5.2 Arduino代码详解从连接到心跳保活#include WiFi.h #include PubSubClient.h #include Wire.h #include Adafruit_SHT31.h // WiFi配置 const char* ssid YourWiFiSSID; const char* password YourWiFiPassword; // MQTT Broker配置 const char* mqtt_server 192.168.1.100; // 替换为你的Mosquitto服务器IP const int mqtt_port 1883; const char* mqtt_user admin; const char* mqtt_password password123; WiFiClient espClient; PubSubClient client(espClient); Adafruit_SHT31 sht31 Adafruit_SHT31(); // 设备唯一ID建议用MAC地址后4位 String deviceId String(ESP.getEfuseMac(), HEX); deviceId deviceId.substring(6); // 取后4位如ABCD void setup() { Serial.begin(115200); delay(1000); // 初始化传感器 if (!sht31.begin(0x44)) { Serial.println(Couldnt find SHT31); } // 连接WiFi connectWiFi(); // 初始化MQTT客户端 client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); } void loop() { // 保持MQTT连接 if (!client.connected()) { reconnect(); } client.loop(); // 处理MQTT收发 // 每30秒上报一次数据 static unsigned long lastMsg 0; unsigned long now millis(); if (now - lastMsg 30000) { lastMsg now; publishSensorData(); } } void connectWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(); Serial.print(WiFi connected, IP address: ); Serial.println(WiFi.localIP()); } void reconnect() { // 等待WiFi连接 if (!client.connected()) { while (!client.connected()) { if (client.connect((ESP32- deviceId).c_str(), mqtt_user, mqtt_password)) { Serial.println(MQTT connected); // 订阅控制Topic如gateway/001/command client.subscribe((gateway/ deviceId /command).c_str()); } else { Serial.print(MQTT connect failed, rc); Serial.print(client.state()); Serial.println( try again in 5 seconds); delay(5000); } } } } void callback(char* topic, byte* payload, unsigned int length) { // 处理下行指令 Serial.print(Message arrived [); Serial.print(topic); Serial.print(] ); String msgStr ; for (int i 0; i length; i) { msgStr (char)payload[i]; } Serial.println(msgStr); // 解析JSON指令如{cmd:led_on,value:1} if (msgStr.indexOf(led_on) ! -1) { digitalWrite(LED_BUILTIN, HIGH); } else if (msgStr.indexOf(led_off) ! -1) { digitalWrite(LED_BUILTIN, LOW); } } void publishSensorData() { float temp sht31.readTemperature(); float humi sht31.readHumidity(); // 构造JSON消息 String json {\temp\: String(temp, 1) ,\humi\: String(humi, 1) ,\ts\: String(millis()) }; // 发布到Topicsensor/ABCD/telemetry String topic sensor/ deviceId /telemetry; bool success client.publish(topic.c_str(), json.c_str(), true); // QoS1 if (success) { Serial.println(Data published: json); } else { Serial.println(Publish failed); } }关键细节说明client.connect((ESP32- deviceId).c_str(), ...)客户端ID用设备MAC后缀确保唯一性。c_str()是C字符串转C风格字符串的必需操作。client.publish(..., true)第三个参数true表示启用Retain让新订阅者立刻获得最新状态。callback函数里msgStr的拼接避免String对象频繁创建销毁导致内存碎片。ESP32内存紧张这种细节决定稳定性。5.3 稳定性加固应对弱网、断电、看门狗的实战技巧ESP32在野外部署最大的敌人不是代码bug而是物理环境WiFi断连自动恢复reconnect()函数里加了while(!client.connected())循环但必须加超时否则卡死。我在reconnect()开头加unsigned long startReconnect millis();循环内判断millis() - startReconnect 30000则放弃强制重启WiFi模块。看门狗防死锁在loop()开头加esp_task_wdt_reset()喂狗。同时在publishSensorData()里如果client.connected()为false直接return避免在断连状态下强行publish导致阻塞。电源波动保护ESP32 GPIO在电压低于3.0V时行为异常。我在setup()里加电压检测float vdd esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_0), adc_chars) / 1000.0; if (vdd 3.1) { Serial.println(Low voltage detected: String(vdd)); ESP.restart(); // 低压重启避免数据错乱 }MQTT心跳优化默认keepAlive是60秒但在移动场景如车载设备建议设为15秒。修改reconnect()里的连接参数if (client.connect((ESP32- deviceId).c_str(), mqtt_user, mqtt_password, NULL, 0, 0, NULL, 15)) { // 最后一个参数是keepAlive秒数注意PubSubClient库的client.connected()返回值有陷阱它只表示TCP连接存在不表示MQTT Session有效。真正可靠的判断是client.connected() client.state() MQTT_CONNECTED。我曾因忽略这点在Broker重启后设备一直显示“connected”却收不到消息最后加了state()校验才解决。6. 常见问题与排查技巧实录那些让我熬夜的Bug6.1 “连不上Broker”问题速查表现象可能原因排查命令/操作解决方案mosquitto_sub报错Connection refusedMosquitto服务未启动net start | findstr mosquittonet start mosquittoConnection timed outWindows防火墙拦截netsh advfirewall firewall show rule nameall | findstr 1883创建入站规则放行1883端口Connection refused设备端Broker IP填错在设备端ping Broker IP确认Broker所在机器IP非127.0.0.1Bad user name or password认证凭据错误mosquitto_sub -h 127.0.0.1 -u admin -P password123 -t test检查mosquitto.conf中password_file路径和内容Connection lost频繁断连Keep Alive设置过短查看
上一篇/下一篇内容由系统自动关联
返回资讯列表 →