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 | |