MQTT协议:IoT通信的轻量级选手

news2025/4/18 0:11:45

文章总结(帮你们节约时间)

  • MQTT协议是一种轻量级的发布/订阅通信协议。
  • MQTT通信包括连接建立、订阅、发布和断开等过程。
  • MQTT基于TCP/IP,其通信过程涉及多种控制包和数据包。
  • ESP32S3可以通过MQTT协议接收消息来控制IO9引脚上的LED。

想象一下,如果互联网是一个繁忙的城市,那么MQTT就像是一个高效的快递系统。而传统HTTP通信?那就是你不得不亲自上门取包裹的情况!MQTT(Message Queuing Telemetry Transport)是物联网世界的通信明星,它轻巧、灵活,特别适合资源受限的设备。这不就像是那种即使在拥挤的小巷里也能灵活穿梭的电动车吗?

MQTT是什么?

MQTT是一种基于发布/订阅模式的轻量级消息传输协议,专为低带宽、高延迟或不稳定网络环境设计。它最初由IBM开发,现已成为物联网领域的标准协议之一。

想象MQTT就像是一个神奇的广播站。你不需要直接联系想要交流的对象,只需对着广播站(MQTT服务器,也称为Broker)说:“我要订阅’天气频道’”。之后,任何发布到"天气频道"的信息,你都能收到!这种解耦的设计使得设备之间不需要知道彼此的存在,大大简化了网络拓扑。

MQTT的核心概念

主题(Topic)

MQTT的主题就像是邮件的地址系统,但更加灵活。主题由层级组成,用斜杠分隔,例如:home/livingroom/temperature

这种层级结构有什么妙处?你可以使用通配符订阅多个主题!例如,订阅home/#就能收到家中所有传感器的数据,而不用一个个地订阅。这不比传统的点对点通信方便多了吗?

QoS(服务质量)

MQTT提供三种服务质量级别:

  • QoS 0:最多一次,“发了就发了,管它收没收到”
  • QoS 1:至少一次,“我会一直发,直到收到确认”
  • QoS 2:正好一次,“我保证消息只送达一次,不多不少”

这就像是你发送一封重要邮件,QoS决定了你会不会追踪它、催促它、确认它是否送达。

MQTT通信过程详解

连接建立过程

想知道MQTT客户端和服务器之间的第一次"握手"是怎样的吗?请看下面的详细步骤:

  1. TCP连接建立:MQTT建立在TCP/IP协议之上,首先需要完成TCP三次握手:

    • 客户端发送SYN包(序列号=x)
    • 服务器回复SYN-ACK包(序列号=y,确认号=x+1)
    • 客户端发送ACK包(确认号=y+1)
  2. CONNECT包发送:TCP连接建立后,客户端发送CONNECT包,包含:

    • 客户端ID
    • 用户名和密码(如果需要认证)
    • 保持连接的时间间隔(Keep Alive)
    • 清除会话标志(Clean Session)
    • 遗嘱信息(Will Message,在客户端异常断开时发送的消息)
  3. CONNACK响应:服务器回复CONNACK包,告知连接是否成功,包含:

    • 连接返回码(0表示成功,其他值表示各种错误)
    • 会话状态标志(指示是否有上一个会话)

想象这个过程就像是你走进一个俱乐部,先向保安出示会员卡(TCP连接),然后向接待员登记你的信息(CONNECT),最后接待员确认你可以进入并告诉你你的会员状态(CONNACK)。

发布/订阅过程

  1. 订阅过程

    • 客户端发送SUBSCRIBE包,指定要订阅的主题和QoS级别
    • 服务器回复SUBACK包,确认订阅并返回授予的QoS级别
  2. 发布过程

    • 发布者发送PUBLISH包,包含主题、消息内容和QoS级别
    • 如果QoS > 0,则需要额外的确认包(PUBACK、PUBREC、PUBREL、PUBCOMP)
  3. QoS 1的消息流

    • 发布者→PUBLISH→服务器
    • 服务器→PUBACK→发布者
    • 服务器→PUBLISH→订阅者
    • 订阅者→PUBACK→服务器
  4. QoS 2的消息流

    • 发布者→PUBLISH→服务器
    • 服务器→PUBREC→发布者
    • 发布者→PUBREL→服务器
    • 服务器→PUBCOMP→发布者
    • 服务器→PUBLISH→订阅者
    • 订阅者→PUBREC→服务器
    • 服务器→PUBREL→订阅者
    • 订阅者→PUBCOMP→服务器

看到这些确认过程,是不是觉得QoS 2有点繁琐?但这正是为了保证消息"正好一次"传递的代价!就像快递公司为了确保贵重包裹安全送达,会要求你签名、拍照、确认收货一样。

保持连接与断开

  • PINGREQ/PINGRESP:客户端定期发送心跳包,服务器回应以保持连接活跃
  • DISCONNECT:客户端发送断开连接的请求,然后关闭TCP连接

这就像是你在图书馆学习,偶尔举手让管理员知道你还在(PING),最后向管理员示意你要离开(DISCONNECT)。

MQTT底层TCP数据包分析

当MQTT协议工作时,TCP层都发生了什么呢?让我们揭开这个神秘的面纱:

  1. TCP连接建立(三次握手):

    客户端 -> [SYN] -> 服务器
    客户端 <- [SYN, ACK] <- 服务器
    客户端 -> [ACK] -> 服务器
    
  2. MQTT CONNECT包

    TCP头部:
      源端口: 随机端口(如43251)
      目标端口: 1883(标准MQTT端口)
      序列号: x
      确认号: y
      标志: PSH, ACK
    
    MQTT数据:
      包类型: CONNECT (1)
      剩余长度: 可变
      协议名: "MQTT"
      协议级别: 4(MQTT v3.1.1)或5(MQTT v5.0)
      连接标志: 用户名、密码、遗嘱等标志位
      保持连接: 通常为60秒
      客户端标识符: 如"esp32_client_001"
      [可选]用户名、密码等
    
  3. MQTT PUBLISH包(QoS 1)

    TCP头部:
      源端口: 随机端口
      目标端口: 1883
      序列号: x+n
      确认号: y+m
      标志: PSH, ACK
    
    MQTT数据:
      包类型: PUBLISH (3)
      剩余长度: 可变
      主题长度: 2字节长度前缀
      主题: 如"home/livingroom/led"
      包ID: 仅当QoS>0时出现
      有效载荷: 如"ON"或"OFF"
    

看到这些细节,你是不是更能理解MQTT的工作原理了?这些看似复杂的数据包,本质上就是设备之间传递的"便条",告诉对方"我想做什么"或"我已经做了什么"。

ESP32S3使用MQTT控制LED实践

是时候将理论付诸实践了!让我们使用ESP32S3通过MQTT协议来控制一个连接到IO9的LED。

硬件准备

  • ESP32S3开发板
  • LED(连接到IO9)
  • 220欧姆电阻
  • 连接线

软件准备

  • 安装Arduino IDE
  • 安装ESP32S3开发板支持
  • 安装PubSubClient库(用于MQTT通信)

代码实现

#include <WiFi.h>
#include <PubSubClient.h>

// WiFi配置
const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";

// MQTT配置
const char* mqtt_server = "你的MQTT服务器地址";
const int mqtt_port = 1883;
const char* mqtt_client_id = "ESP32S3_LED_Controller";
const char* mqtt_topic = "home/esp32s3/led";

// LED引脚
const int ledPin = 9;  // IO9

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  delay(10);
  Serial.println("连接到WiFi...");
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("WiFi已连接");
  Serial.print("IP地址: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  // 将接收的字节数组转换为字符串
  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  
  Serial.print("收到消息: ");
  Serial.println(message);
  
  // 控制LED
  if (message.equals("ON")) {
    digitalWrite(ledPin, HIGH);
    Serial.println("LED已打开");
  } else if (message.equals("OFF")) {
    digitalWrite(ledPin, LOW);
    Serial.println("LED已关闭");
  }
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("尝试MQTT连接...");
    
    if (client.connect(mqtt_client_id)) {
      Serial.println("已连接");
      
      // 订阅控制主题
      client.subscribe(mqtt_topic);
    } else {
      Serial.print("连接失败,错误码=");
      Serial.print(client.state());
      Serial.println(" 5秒后重试");
      delay(5000);
    }
  }
}

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);
  
  setup_wifi();
  
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  
  // 处理MQTT消息
  client.loop();
}

实现分析

当我们运行这个程序时,ESP32S3会:

  1. 连接到WiFi网络
  2. 连接到MQTT服务器
  3. 订阅home/esp32s3/led主题
  4. 等待控制命令

当我们通过MQTT客户端(如MQTT Explorer或手机App)发布"ON"或"OFF"消息到home/esp32s3/led主题时,ESP32S3会接收到消息并相应地控制LED。

这个过程中发生的TCP和MQTT通信可以通过Wireshark捕获。发布"ON"消息时,我们将看到:

  1. MQTT PUBLISH包从发布者到MQTT服务器
  2. MQTT服务器将PUBLISH包转发给ESP32S3
  3. ESP32S3接收到PUBLISH包,解析内容,发现是"ON"
  4. ESP32S3控制IO9引脚输出高电平,点亮LED

这就像是我们在微信群(MQTT服务器)里发了一条消息"开灯",而ESP32S3正好在看这个群,看到消息后立即执行了开灯的动作!

MQTT的安全性考虑

在实际应用中,安全性至关重要。MQTT本身并不提供加密,但可以通过以下方式增强安全性:

  1. 使用MQTT over TLS/SSL:使用8883端口而不是标准的1883端口
  2. 客户端身份验证:使用用户名/密码或客户端证书
  3. 访问控制列表(ACL):在服务器端配置,限制客户端可以发布/订阅的主题

想象一下,这就像是给你的微信群设置了密码,并且限制了谁能发言、谁能看到消息。在物联网世界,这种保护措施不是可选的,而是必须的!

MQTT的高级特性

除了基本功能外,MQTT还有一些高级特性:

  1. 保留消息:服务器会保存标记为"保留"的消息,新订阅者连接时立即收到
  2. 遗嘱消息:客户端异常断开时自动发布的消息
  3. 共享订阅:多个客户端共享同一个订阅,实现负载均衡
  4. MQTT 5.0新特性:消息过期、主题别名、用户属性等

这些功能让MQTT变得更加强大和灵活。就像一个初看简单的瑞士军刀,打开后却发现它能完成各种意想不到的任务!

MQTT与其他协议的对比

为什么选择MQTT而不是其他协议?让我们做个对比:

特性MQTTHTTPCoAPAMQP
协议模型发布/订阅请求/响应请求/响应发布/订阅
消息开销极小中等
QoS级别0,1,2可靠/不可靠复杂QoS
适用场景低带宽网页应用资源受限企业消息

看到这个对比,你会发现MQTT在物联网场景中的优势多么明显!它就像是专为物联网"量身定制"的通信协议。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2331097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GNSS有源天线和无源天线

区别 需要外部供电的就是有源天线&#xff0c;不需要外部供电的是无源天线。 无源天线 一般就是一个陶瓷片、金属片等&#xff0c;结构简单&#xff0c;成本低廉&#xff0c;占用空间及体积小&#xff0c;适合于强调紧凑型空间的导航类产品。 不需要供电&#xff0c;跟设备直…

欧税通香港分公司办公室正式乔迁至海港城!

3月20日&#xff0c;欧税通香港分公司办公室正式乔迁至香港油尖旺区的核心商业区海港城!左手挽着内地市场&#xff0c;右手牵起国际航道——这波乔迁选址操作堪称“地理课代表”! 乔迁仪式秒变行业大联欢!感谢亚马逊合规团队、亚马逊云、阿里国际站、Wayfair、coupang、美客多…

ETPNav:基于演进拓扑规划的连续环境视觉语言导航模型

1、现有工作的缺陷&#xff1a; 最近&#xff0c;出现了一种基于模块化航路点的方法的新兴趋势&#xff0c;该方法将复杂任务分为航路点生成、子目标规划和导航控制&#xff1a; &#xff08;1&#xff09;在每个决策循环中&#xff0c;代理使用预训练的网络来预测附近的几个…

Spring Cloud LoadBalancer负载均衡+算法切换

目录 介绍核心功能负载均衡启动两个支付服务订单模块引入依赖LoadBalanced 注解启动订单服务测试结果 负载均衡算法切换总结 介绍 Spring Cloud LoadBalancer 是 Spring Cloud 提供的客户端负载均衡解决方案&#xff0c;提供更现代化的 API 和更好的 Spring 生态系统集成。它支…

游戏引擎学习第210天

回顾并为今天的工作做准备 今天我们&#xff0c;进行一些编码工作。这部分的编码内容对那些对代码架构感兴趣的人非常有帮助&#xff0c;我认为今天的编码内容会很有教育意义&#xff0c;尤其是在展示一些代码转化的过程中&#xff0c;希望大家能够从中获得一些启发。 接下来…

UML类图综合实验三补档

1.使用简单工厂模式模拟女娲(Nvwa)造人(Person)&#xff0c;如果传入参数“M”&#xff0c;则返回一个Man对象&#xff0c;如果传入参数“W”&#xff0c;则返回一个Woman对象&#xff0c;用Java语言实现该场景。现需要增加一个新的Robot类&#xff0c;如果传入参数“R”&#…

WinForm真入门(11)——ComboBox控件详解

WinForm中 ComboBox 控件详解‌ ComboBox 是 WinForms 中一个集文本框与下拉列表于一体的控件&#xff0c;支持用户从预定义选项中选择或直接输入内容。以下从核心属性、事件、使用场景到高级技巧的全面解析&#xff1a; 一、ComboBox 核心属性‌ 属性说明示例‌Items‌下拉…

DeepSeek底层揭秘——《推理时Scaling方法》技术对比浅析

4月初&#xff0c;DeepSeek 提交到 arXiv 上的最新论文正在 AI 社区逐渐升温。 笔者尝试对比了“关于推理时Scaling”与现有技术&#xff0c;粗浅分析如下&#xff1a; 与LoRA的对比 区别&#xff1a; 应用场景&#xff1a;LoRA是一种参数高效微调方法&#xff0c;主要用于在…

Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(四)

Android Coli 3 ImageView load two suit Bitmap thumb and formal&#xff0c;Kotlin&#xff08;四&#xff09; 对 Android Coli 3 ImageView load two suit Bitmap thumb and formal&#xff0c;Kotlin&#xff08;三&#xff09;-CSDN博客 进行完善&#xff0c;注意完善 …

Adam优化器研究综述

摘要 Adam优化器&#xff08;Adaptive Moment Estimation&#xff09;是一种广泛应用于深度学习的优化算法&#xff0c;通过自适应学习率加速梯度下降过程。本文从Adam的定义、算法原理、优势与局限性、应用场景及变体等方面进行调研&#xff0c;结合学术文献和实践经验&#x…

在 macOS 上连接 PostgreSQL 数据库(pgAdmin、DBeaver)

在 macOS 上连接 PostgreSQL 数据库 pgAdmin 官方提供的图形化管理工具&#xff0c;支持 macOS。 下载地址&#xff1a;https://www.pgadmin.org/ pgAdmin 4 是对 pgAdmin 的完全重写&#xff0c;使用 Python、ReactJs 和 Javascript 构建。一个用 Electron 编写的桌面运行时…

2018年真题

数学基础 一、 &#xff08;共4分&#xff09;用逻辑符号表达下列语句&#xff08;论域为包含一切事物的集合&#xff09; 1、&#xff08;2分&#xff09;集合A的任一元素的元素都是A的元素 经过对图片文字的识别与逻辑分析&#xff0c;结果如下&#xff1a; 符号定义&…

Efficient Burst Raw Denoising:稳定噪声方差和分频率降噪

Efficient Burst Raw Denoising with Stabilization and Multi-Frequency Denoising Network Burst Raw Denoising必要性Burst Raw Image Denoising流程Main Contributions具体方法介绍集成noise priorCMOS sensor 噪声建模噪声变换&#xff08;Variance stabilization&#xf…

mapbox进阶,使用本地dem数据,加载hillshade山体阴影图层

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️hillshade 山体阴影图层 api1.3.1 ☘️…

【C++】Stack Queue 仿函数

&#x1f4dd;前言&#xff1a; 这篇文章我们来讲讲STL中的stack和queue。因为前面我们已经有了string、vector和list的学习基础&#xff0c;所以这篇文章主要关注一些stack和queue的细节问题&#xff0c;以及了解一下deque&#xff08;缝合怪&#xff09;和priority_queue &am…

代码随想录_单调栈

代码随想录_单调栈 739.每日温度 739. 每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;…

BoostSearch搜索引擎项目 —— 测试用例设计 + web自动化测试代码

web自动化代码&#xff1a; https://gitee.com/chicken-c/boost-search/tree/master/AutoTest

【Ansible自动化运维】一、初步了解,开启自动化运维之旅

在当今数字化时代&#xff0c;随着企业 IT 基础设施规模的不断扩大&#xff0c;传统的手工运维方式逐渐显得力不从心。自动化运维技术应运而生&#xff0c;其中 Ansible 凭借其简洁易用、功能强大的特点&#xff0c;成为众多运维工程师和开发人员的首选工具。本篇文章将从基础概…

条件概率、概率乘法公式、全概率公式和贝叶斯 (Bayes) 公式

定义 设 P ( A ) > 0 P(A) > 0 P(A)>0&#xff0c;若在随机事件 A A A发生的条件下随机事件 B B B发生的概率记作 P ( B ∣ A ) P(B|A) P(B∣A)&#xff0c;定义 P ( B ∣ A ) P ( A B ) P ( A ) P(B|A) \frac{P(AB)}{P(A)} P(B∣A)P(A)P(AB)​ 则称 P ( B ∣ A ) …

kotlin,Android,jetpack compose,日期时间设置

AI生成&#xff0c;调试出来学习&#xff0c;这些小组件会用了&#xff0c;就可以组合一个大点的程序了。 package com.example.mydatetimeimport android.app.AlertDialog import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.co…