自己动手实现MQTT协议
写在前面
前段时间弄IoT相关的东西,系统学习了一下 MQTT 协议,在此分享出来。
本文先是对 MQTT 协议做了简单的介绍;接着是对 MQTT协议的内容做了较为全面的解读;最后使用 Python 语言去实现一个简单的 MQTT 客户端和服务器。
简介
MQTT 全称是 Message Queue Telemetry Transport,翻译成中文意思是“遥测传输协议”。它最先是由IBM提出,是一种基于 **TCP ** 协议,具有简单、轻量等优点,特别适合于受限环境(带宽低、网络延迟高、网络通信不稳定)的消息分发。MQTT 协议有 3.x, 5.x 等多个版本,目前最常用的版本是 v3.1.1 ,本文也是对此版本的协议进行的解读。MQTT 协议已纳入ISO标准 (ISO/IEC PRF 20922),现今主流的 IoT 平台都支持该协议。
快速开始
MQTT 是一种发布-订阅协议,这意味着:
- 客户端(Client)可以向服务端(Broker) 订阅(Subscribe)自己感兴趣的主题(Topic);
- 客户端还可以向服务端发布(Publish)关于某个主题的信息(主题不需要提前创建,发布消息时指定即可);
- 服务端在收到客户端发布的消息后,会将该消息转发给订阅了该主题的其他客户端。
我们可以在自己的电脑上运行一个 MQTT 的服务端,和多个 MQTT 的客户端来体验这一过程。
MQTT 服务端有很多可以选择。这里我们使用 Mosquitto,按照其官方文档的说明安装即可,这里不多做介绍。
Mac 用户可以用以下命令安装并启动 Mosquitto:
brew install mosquitto
brew services start mosquitto
Mosquitto 提供了命令行工具 mosquitto_sub 和 mosquitto_pub ,它们可用来向服务端订阅主题 和发布消息。
在一个命令行窗口中,执行以下命令去订阅名为 “foo” 的主题:
mosquitto_sub -h 127.0.0.1 -p 1883 -t foo -q 2
在另一个命令行窗口中,执行以下命令发布消息 “Hello, MQTT” 到 “foo” 主题:
mosquitto_pub -h 127.0.0.1 -p 1883 -t foo -q 2 -m 'Hello, MQTT'
最终我们将看到,在第一个命令行窗口中,打印出了消息 “Hello, MQTT”。这意味着,第一个客户端在主题 “foo” 上,收到了第二个客户端发布的消息。
协议详解
数据包整体格式
从整体上看,数据包分为3个部分:一个是固定头部,它是一定存在的;另一个是可变头部,它不一定存在;剩下一个是载荷,它也不一定存在。数据采用大端方式存储。
+----------------------------+
| |
| 固 定 头 部 (必 需 ) |
| |
+----------------------------+
| |
| 可 变 头 部 (非 必 需) |
| |
+----------------------------+
| |
| 载 荷 (非 必 需 ) |
| |
+----------------------------+
固定头部(Fixed header)
固定头部格式如下:
+---------------------------------------------------------+
| bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---------------------------------------------------------+
| byte1 | Packet type | Flags |
+---------------------------------------------------------+
| byte2...| Remaining Length |
+---------------------------------------------------------+
包类型(Packet type)
Name | Value | Direction of flow | Description |
---|---|---|---|
Reserved | 0 | Forbidden | Reserved |
CONNECT | 1 | Client to Server | Client request to connect to Server |
CONNACK | 2 | Server to Client | Connect acknowledgment |
PUBLISH | 3 | Client to Server or Server to Client | Publish message |
PUBACK | 4 | Client to Server or Server to Client | Publish acknowledgment |
PUBREC | 5 | Client to Server or Server to Client | Publish received (assured delivery part 1) |
PUBREL | 6 | Client to Server or Server to Client | Publish release (assured delivery part 2) |
PUBCOMP | 7 | Client to Server or Server to Client | Publish complete (assured delivery part 3) |
SUBSCRIBE | 8 | Client to Server | Client subscribe request |
SUBACK | 9 | Server to Client | Subscribe acknowledgment |
UNSUBSCRIBE | 10 | Client to Server | Unsubscribe request |
UNSUBACK | 11 | Server to Client | Unsubscribe acknowledgment |
PINGREQ | 12 | Client to Server | PING request |
PINGRESP | 13 | Server to Client | PING response |
DISCONNECT | 14 | Client to Server | Client is disconnecting |
Reserved | 15 | Forbidden | Reserved |
标记(Flags)
不同包类型标记位含义不尽相同,具体情况如下表所示:
Control Packet | Fixed header flags | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|
CONNECT | Reserved | 0 | 0 | 0 | 0 |
CONNACK | Reserved | 0 | 0 | 0 | 0 |
PUBLISH | Used in MQTT 3.1.1 | DUP1 | QoS2 | QoS2 | RETAIN3 |
PUBACK | Reserved | 0 | 0 | 0 | 0 |
PUBREC | Reserved | 0 | 0 | 0 | 0 |
PUBREL | Reserved | 0 | 0 | 1 | 0 |
PUBCOMP | Reserved | 0 | 0 | 0 | 0 |
SUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
SUBACK | Reserved | 0 | 0 | 0 | 0 |
UNSUBSCRIBE | Reserved | 0 | 0 | 1 | 0 |
UNSUBACK | Reserved | 0 | 0 | 0 | 0 |
PINGREQ | Reserved | 0 | 0 | 0 | 0 |
PINGRESP | Reserved | 0 | 0 | 0 | 0 |
DISCONNECT | Reserved | 0 | 0 | 0 | 0 |
剩余长度(Remaining Length)
Remaining Length 表示的是本数据包剩余部分的字节数,即可变头部和载荷的字节数之和。为了节省传输时的字节数,Remaining Length 采用的是一种变长编码方式。这就是说 Remaining Length 字段的字节数不是固定的,它可能使用1~4个字节。既然 Remaining Length 的字节数是可变的,那么问题来了,我们在解码包数据的时候,怎么知道 Remaining Length 究竟是使用几个字节编码的呢?解决这个问题的办法是,将每个字节的最高位(MSB)作为标志位。若该位的值是1,则意味着下一个字节属于参与 Remaining Length 编码的字节;若该位的值是0,则意味着本字节已经是最后一个参与 Remaining Length 编码的字节了。
举几个
自己动手实现MQTT协议的更多相关文章
- 海鑫智圣:物联网漫谈之MQTT协议
什么是MQTT协议 MQTT(消息队列遥测传输协议)是IBM在1999年专门针对物联网等应用场景来制订的轻量级双向消息传输协议,它主要是为了解决物联网上使用到的设备的互相通信的问题,以及这些设备与后端 ...
- 基于MQTT协议进行应用开发
官方协议有句如下的话来形容MQTT的设计思想: "It is designed for connections with remote locations where a "sma ...
- 云巴:基于MQTT协议的实时通信编程模型
概要 有人常问,云巴实时通信系统到底提供了一种怎样的服务,与其他提供推送或 IM 服务的厂商有何本质区别.其实,从技术角度分析,云巴与其它同类厂商都是面向开发者的通信服务,宏观的编程模型都是大同小异, ...
- MQTT协议(一)
MQTT(Message Queue Telemetry Transport),遥测传输协议,提供订阅/发布模式,更为简约.轻量,易于使用,针对受限环境(带宽低.网络延迟高.网络通信不稳定),可以简单 ...
- MQTT协议的简单介绍和服务器的安装
最近公司做的项目中有用到消息推送,经过多方面的筛选之后确定了使用MQTT协议,相对于XMPP,MQTT更加轻量级,并且占用用户很少的带宽. MQTT是IBM推出的一种针对移动终端设备的基于TCP/IP ...
- MQTT协议学习笔记
1.前沿 万物联网的时代即将到来,物联网也由当初的概念开始进一步落实.随着无线网络技术飞速发展,各种设备都可以连接网络,实现远程控制.例如智能家居最近非常火爆,智能插座.智能LED灯.智能摄像头等.在 ...
- 【转载】MQTT学习笔记——MQTT协议体验 Mosquitto安装和使用
http://blog.csdn.net/xukai871105/article/details/39252653 0 前言 MQTT是IBM开发的一个即时通讯协议.MQTT是面向M2M和物联 ...
- 转:XMPP协议、MQTT协议、HTTP协议、CoAP协议的基本比较
一.先看下相关国外的专业数据对四大协议的比较: Protocol CoAP XMP ...
- 物联网MQTT协议分析和开源Mosquitto部署验证
在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定 ...
随机推荐
- Bzoj 3166 [Heoi2013] Alo 题解
3166: [Heoi2013]Alo Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1118 Solved: 518[Submit][Status ...
- idea中向pom.xml添加依赖时显示”not found dependency“
总结: 起因:再输入hibernate-core的version时,开始写的是对的,就是 5.0.11.Final(这个也是跟着教程来的),直接就报错了,左等右等没用,也点过maven的reimpor ...
- python笔记(1)--序列(列表 元组 range)
一.序列分类 1.可变序列:list 2.不可变序列:tuple,range 二.序列公共操作方法 1.操作和返回值 其中s和t代表同类型序列:n,i,j,k为整数:x为任意类型. 序号 操作 结果 ...
- Windows 10打开远程桌面的方法
今天使用windows 10,想要用远程桌面连接,可是怎么都找不到,哎,win10相比于win7和XP系统,感觉还是有点使用不习惯.不过后来还是找到了两个方法,在此记录下来,分享给需要的朋友. 1. ...
- 20131209-数据库导入导出数据-sqlhelper-第十七天
[1] 导出数据 namespace _05导出数据 { class Program { static void Main(string[] args) { string str = "Da ...
- springcloud-高可用部署
1.场景描述 前端时间只简单介绍了下springcloud的高可用方案(springcloud高可用方案),今天详细介绍下如何实施springcloud的高可用部署. 2.解决方案 2.1 架构方案 ...
- YuniKorn 介绍
一.YuniKorn 简介 YuniKorn 是一种轻量级的通用资源调度程序,适用于容器编排系统.它的创建是为了一方面在大规模,多租户环境中有效地实现各种工作负载的细粒度资源共享,另一方面可以动态地创 ...
- PJzhang:python基础入门的7个疗程-five
猫宁!!! 参考链接:易灵微课-21天轻松掌握零基础python入门必修课 https://www.liaoxuefeng.com/wiki/1016959663602400 第十三天:代码组织 类是 ...
- 个人永久性免费-Excel催化剂功能第30波-工作表快捷操作(批量创建、命名、排序、工作表目录)
日常使用Excel过程中,最多的操作无外乎单元格和工作表的操作,单元格的操作在前面已经有详细的辅助功能提供,此篇提供工作表相关的操作.这两项的操作若能有提速,日常大量的工作叠加起来真是省下不少时间. ...
- 编译Tomcat9源码及tomcat乱码问题解决
因工作原因,需要从根本上优化tomcat的配置,故准备从源码入手,看看可以做哪些工作. 1. tomcat下载 tomcat最新的版本为9,下载源码的方式有3种: 1/ 官方网站 https://to ...