MQTT(MQ Telemetry Transport,消息队列遥测传输)是近年来出现的一种新型协议,物联网领域也许会将其作为标准协议。MQTT 原本是 IBM 公司开发的协议,现在已经开源了,被更多人共同开发着。
MQTT 是一种能实现一对多通信(通常被称为发布/订阅型)的协议。如下图所示,它由三部分组成,分别是代理服务或中介(broker)、发布者(publisher)和订阅者(subscriber)。
简单来说,中介扮演的是 MQTT 通信服务器的角色,而发布者和订阅者则扮演客户端的角色。发布者是负责发送消息的客户端,而订阅者是负责接收消息的客户端。MQTT 交换的消息都附带着主题(topic)地址,各个客户端把这个“主题”视为收信地址,对其执行传输消息的操作。所以,大家不妨将中介想象成接收邮件的邮箱。
好了,本文的目的是体验 MQTT,关于 MQTT 的更多细节将在后面的文章的介绍。
mosquitto 是一款实现了消息推送协议 MQTT v3.1 的开源消息代理软件,提供轻量级的,支持可发布/可订阅的的消息推送模式,使设备对设备之间的短消息通信变得简单,比如现在应用广泛的低功耗传感器,手机、嵌入式计算机、微型控制器等移动设备。一个典型的应用案例就是 Andy Stanford-ClarkMosquitto(MQTT协议创始人之一)在家中实现的远程监控和自动化。并在 OggCamp 的演讲上,对MQTT协议进行详细阐述。
我这里的实验环境是32位的 Ubuntu 12.04 系统,安装的 mosquitto 版本是 1.4.5。
编译过程中可能会提示找不到 openssl/ssl.h、ares.h、uuid/uuid.h等目录或文件,所以需要执行以下命令安装依赖:
sudo apt-get install libssl-dev libc-ares-dev uuid-dev
不同平台和版本可能会有不同依赖,大家根据提示进行安装即可。下面进行 mosquitto 的安装:
(1)下载源代码包
$ wget http://mosquitto.org/files/source/mosquitto-1.4.5.tar.gz
(2)解压
$ tar zxvf mosquitto-1.4.5.tar.gz
(3)进入目录
$ cd mosquitto-1.4.5
(4)编译
$ make
编译完之后我们可以在 lib/ 目录下找到 libmosquitto.so.1,在 src/ 目录下找到 mosquitto 和 mosquitto_passwd,在 client/ 目录下找到 mosquitto_pub 和 mosquitto_sub。
(5)安装
$ sudo make install
到这里,mosquitto 就已经安装好了,libmosquitto.so.1 库被安装在 /usr/local/lib/ 目录下。但是在运行时可能会提示“error while loading shared libraries: libmosquitto.so.1”,解决的办法是将这个动态链接库的路径添加到环境变量 LD_LIBRARY_PATH 中,或者创建软链接:
$ sudo ln -s /usr/local/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1
上面采用的是源码安装方法,实际上还有更简单的方法 (^_^),比如:
$ sudo apt-get install mosquitto mosquitto-clients
此次初体验测试在一台 PC 上即可完成,包括一个中介(broker)、一个发布者(publisher)和多个订阅者(subscriber)。测试步骤如下:
(1)启动代理服务(中介)mosquitto。
$ mosquitto -v
参数 -v 是为了打印更多的调试信息。
(2)另打开一个或多个 terminal,使用 mosquitto_sub 启动一个或多个订阅者订阅“sensor”主题的消息。
$ mosquitto_sub -v -t sensor
参数 -v 是为了打印更多的调试信息,参数 -t 用于指定主题。
(3)另打开一个 terminal,使用 mosquitto_pub 启动一个发布者发布“sensor”主题的消息。
$ mosquitto_pub -t sensor -m 25
参数 -t 用于指定主题,参数 -m 用于指定消息内容。
(4)上一步骤完成了发布者连接中介并发送消息的操作,我们可以看到订阅者中同时显示 sensor 25
的内容,即 MQTT 中介已经向订阅了“sensor”主题的订阅者成功传送消息。
在启动中介的时候我们加了 -v 参数,那么我们来看看打印出来的调试信息:
rudy@ubuntu12:~$ mosquitto -v
/* ****** 启动中介 ****** */
1501313682: mosquitto version 1.4.5 (build date 2017-07-29 11:54:27+0800) starting
1501313682: Using default config.
1501313682: Opening ipv4 listen socket on port 1883.
1501313682: Opening ipv6 listen socket on port 1883.
/* ****** 第1个订阅者 ****** */
1501313744: New connection from 127.0.0.1 on port 1883.
1501313744: New client connected from 127.0.0.1 as mosqsub/14095-ubuntu12 (c1, k60).
1501313744: Sending CONNACK to mosqsub/14095-ubuntu12 (0, 0)
1501313744: Received SUBSCRIBE from mosqsub/14095-ubuntu12
1501313744: sensor (QoS 0)
1501313744: mosqsub/14095-ubuntu12 0 sensor
1501313744: Sending SUBACK to mosqsub/14095-ubuntu12
/* ****** 第2个订阅者 ****** */
1501313751: New connection from 127.0.0.1 on port 1883.
1501313751: New client connected from 127.0.0.1 as mosqsub/14096-ubuntu12 (c1, k60).
1501313751: Sending CONNACK to mosqsub/14096-ubuntu12 (0, 0)
1501313751: Received SUBSCRIBE from mosqsub/14096-ubuntu12
1501313751: sensor (QoS 0)
1501313751: mosqsub/14096-ubuntu12 0 sensor
1501313751: Sending SUBACK to mosqsub/14096-ubuntu12
/* ****** 发布者连接并发布消息 ****** */
1501313766: New connection from 127.0.0.1 on port 1883.
1501313766: New client connected from 127.0.0.1 as mosqpub/14097-ubuntu12 (c1, k60).
1501313766: Sending CONNACK to mosqpub/14097-ubuntu12 (0, 0)
1501313766: Received PUBLISH from mosqpub/14097-ubuntu12 (d0, q0, r0, m0, 'sensor', ... (2 bytes))
1501313766: Sending PUBLISH to mosqsub/14095-ubuntu12 (d0, q0, r0, m0, 'sensor', ... (2 bytes))
1501313766: Sending PUBLISH to mosqsub/14096-ubuntu12 (d0, q0, r0, m0, 'sensor', ... (2 bytes))
1501313766: Received DISCONNECT from mosqpub/14097-ubuntu12
1501313766: Client mosqpub/14097-ubuntu12 disconnected.
/* ****** 定时心跳 ****** */
1501313804: Received PINGREQ from mosqsub/14095-ubuntu12
1501313804: Sending PINGRESP to mosqsub/14095-ubuntu12
1501313811: Received PINGREQ from mosqsub/14096-ubuntu12
1501313811: Sending PINGRESP to mosqsub/14096-ubuntu12
/* ****** ...... ****** */
通过上述的测试以及这些调试信息,相信大家已经对 MQTT 协议的工作流程有一个整体的认识,这也是本文的目的。
关于 mosquitto、mosquitto_pub 及 mosquitto_sub 的更多用法,可以通过参数 –help 来了解。