自己动手实现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制定 ...
随机推荐
- JsonUtil(基于Jackson的实现)
JsonUtil(基于Jackson的实现) 前言: 其实,我一直想写一个有关Util的系列. 其中有四个原因: Util包作为项目的重要组成,是几乎每个项目不可或缺的一部分.并且Util包的Util ...
- JAVA十大经典排序算法最强总结(含JAVA代码实现)
十大经典排序算法最强总结(含JAVA代码实现) 最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在“桶排序”算法中对每 ...
- 关于导入别人的web项目,tomcat无法显示的问题
这两天头大,老师讲了javaWeb项目,讲完就给我们发了代码,我就想导入直接用,结果它tomcat的add and remove 里一直没有这个项目名字 刚导入还报错,这个可能我的版本太低了,兼容不了 ...
- vbox 设置时间不与主机同步
C:\Users\2345-lp0395>"D:\Program Files\Oracle\VirtualBox\VBoxManage.exe" setexadata win ...
- Gitlab Runner实现NetCore自动化持续集成
目录 1.开发工具 2.GitLab服务器搭建 3.新建webapi 4.Dockerfile配置 5.配置docker-compose.yml 6.配置.gitlab-ci.yml 7.在GitLa ...
- InstantiationException:mybatis.spring.transaction.SpringManagedTransactionFactory
问题表现 Error creating bean with name 'sqlSessionFactory' Invocation of init method failed; nested exce ...
- python虚拟环境管理 Pipenv 使用说明
安装 pip install pipenv 检查是否安装成功 pipenv --version 创建虚拟环境(在工程文件夹下) pipenv install 默认下,Pipenv统一管理所有虚拟环境 ...
- 没事别想不开做Halcon视觉工程师 halcon机器视觉如何学习?
今天我们来听听看来自一个机器视觉工程师的唠叨和吐槽,在这之后,你还想学人工智能,还想学机器视觉?恭喜你,你对人工智能机器视觉是真爱了! 既然自己选择了这条路,那么无论前进路上有多坎坷,跪着也要走完. ...
- idea中写servlet时报错--关于405错误
将super方法注释掉 原因:super是调用了此类继承父类doget和dopost方法的, 如果此类中没有这个方法,就会报错The specified HTTP method is not allo ...
- java抽奖思路
现在在做一个有关抽奖的活动,将我自己所做的抽奖思路书写一下 1.项目奖项的配置存储在MongoDB 配置的参数为 奖项的等级(prizeLevel).数量(prizeNum).奖项的名称(prizeN ...