MQTT开发杂记
tl;dr
由于毕设需要用到mqtt
网络协议栈,但这个协议我一直没用过,所以打算写这篇博客来记录一下搭建过程。
MQTT
的工作流程
这是一个需要中心化服务器的协议。中心服务器通常称为broker
,
MQTT(Message Queuing Telemetry Transport) 是一种轻量级的、基于发布/订阅模式的通信协议,常用于物联网设备之间的通信废话。
其工作流程如下:
- 连接建立阶段:
- 客户端通过
TCP
连接到MQTT
代理服务器(通常称为MQTT Broker
)。 - 客户端发送
CONNECT
报文,包含客户端ID、用户名、密码等信息。 - 服务器响应
CONNACK
报文,表示连接建立成功或失败。
- 客户端通过
- 订阅主题:
- 客户端发送
SUBSCRIBE
报文,指定感兴趣的主题和QoS
级别。 - 服务器记录客户端的订阅关系。
- 客户端发送
- 发布消息:
- 客户端发送
PUBLISH
报文,包含主题和消息内容。 - 服务器将消息传送给所有订阅了相应主题的客户端。
- 客户端发送
- 接收消息:
- 客户端接收到服务器发送的
PUBLISH
报文,获取消息内容。
- 客户端接收到服务器发送的
- 取消订阅:
- 客户端发送
UNSUBSCRIBE
报文,取消对某个主题的订阅。
- 客户端发送
- 断开连接:
- 客户端或服务器可以发送
DISCONNECT
报文,正常断开连接。
- 客户端或服务器可以发送
当有n个客户端订阅了同一个主题we_are_ikun
,这n个人谁都可以publish
一条包含自定义内容的报文jntm
,随后经由broker
,会将该消息转发给包括他的所有订阅了we_are_ikun
的终端上。此时,其他终端里任何一个人也可以再publish
一条包含自定义消息的报文ni gan ma haha aiyo amagi
,该报文会经由broker
再转发给包括他的所有终端。
是不是很像一个聊天室?对没错!就想象是一群
小黑子ikun呆在同一个房间里一起谈论哥哥的篮球和背带一样,A说的话能被房间里其他人听到,B说的话也可以被其他人听到。
服务器搭建
我使用的测试服务器是运行在VMware
中的Alpine Linux
,连接模式选择桥接,以便可以和esp8266
在同一个子网下。
我使用的客户端有两台,一台是上述虚拟机,一台是我的安卓手机,使用termux
。
在装好了系统的虚拟机中安装好mosquitto
和mosquitto-clients
软件包。
在termux
中安装mosquitto
软件包,不需要安装clients包,因为它包含了mosquitto_pub
和mosquitto_sub
两个程序。
详见GitHub issues #613。
使用虚拟机和termux
进行简单的MQTT
通信实验
本教程参考官方repo的readme
在虚拟机中定位到配置文件/etc/mosquitto/mosquitto.conf
:
在
termux
中,该配置文件的路径是/data/user/0/com.termux/files/usr/etc/mosquitto/mosquitto.conf
取消注释log_type all
以将日志等级设置为all
,将log_dest
设置为stdout
,要不然不会在屏幕上显示日志。
或者直接添加下面两行也行:我后来试了一下日志等级不设其实也ok
1 |
|
添加以下两行以开启在0.0.0.0
监听、允许匿名登录:
1 |
|
在虚拟机的tty1
中启动mosquitto
服务端程序(使用默认端口1883
开服):
1 |
|
进入tty2
和termux
,订阅testTopic
的主题:
1 |
|
进入tty3
,向主题publish
一条消息:
1 |
|
回到tty2
,看看是不是多了一条来自tty3
的消息?termux
里是不是也有这条消息?
进入termux
,再开一个session
,向主题publish
一条消息:
1 |
|
回到上一个session
,看看是不是多了这条消息?tty2
里是不是也多了这条消息?
如何确保MQTT
通信的安全?
这就是简单的MQTT
通信实验。我们上点难度:加个鉴权。MQTT
支持密码和密钥两种认证方式,我们先从密码开始。参考mqtt官方文档
进入虚拟机,停掉刚刚那个谁都可以加进来的mqtt服务器,编辑/etc/mosquitto/mosquitto.conf
,将allow_anonymous
设置为false
,再添加一行,指向存放密码文件的路径(记得创建这个文件):
1 |
|
⚠注意:在
Linux
上,需要将密码文件存放到/etc/mosquitto
下,要不然就算你在mosquitto.conf
中写入了password_file
,也无法读取密码文件。
添加用户 -方法 1
往/etc/mosquitto/passwordfile
里写入账号和明文密码,一行一个,像这样:
1 |
|
然后运行这行命令来将密码文件加密。
1 |
|
如果有用户是在加密过之后再被添加,写了明文密码,需要再运行一次加密,但是这次加密的时候,系统会只加密明文密码,之前被加密过的密文不会被二次加密。
密码文件必须加密后才能被读取使用!
添加用户 -方法 2
现在,我们添加一个用户,叫alpine
,密码a123456
:
1 |
|
然后系统会提示你输入该用户的密码,和linux设置用户密码一样。
现在,我们再添加一个用户,叫termux
,密码t123456
:
1 |
|
注意这里的参数!
-c
是在没有任何用户的情况下,初始化密码文件用。会覆盖写入文件-b
是在有用户的情况下使用。会追加写入文件。增加用户时命令行里需要传递明文密码了。
现在,我们删除一个用户,把上面的user1
删了:
1 |
|
在运行的时候,没有关闭mosquitto
服务器,但添加/删除了用户,怎么重新加载配置文件呢?新开一个终端(或者tty
),运行下面这个命令即可:
1 |
|
然后就能在运行着mosquitto
的终端里看到Reloading config.
的提示了,此时新的用户清单会被应用。
怎么连接呢?
使用 mosquitto_sub
进行订阅,该话题下所有的消息都会显示在这里:
1 |
|
使用 mosquitto_pub
往指定的话题publish
内容:
1 |
|