[2]MQTT基础知识
MQTT(消息队列遥测传输)是一个客户端服务端架构的发布/订阅模式的消息传输协议。
MQTT协议最初版本是在1999年建立的。该协议的发明人是的Andy Stanford-Clark和Arlen Nipper。
MQTT协议是当今世界上最受欢迎的物联网协议,广泛应用于车联网、智能家居、即时聊天应用和工业互联网等领域。
MQTT协议基本原理
MQTT服务端:MQTT服务端通常是一台服务器。它是MQTT信息传输的枢纽,负责将MQTT客户端发送来的信息传递给MQTT客户端。MQTT服务端还负责管理MQTT客户端。确保客户端之间的通讯顺畅,保证MQTT消息得以正确接收和准确投递。
MQTT客户端:MQTT客户端可以向服务端发布信息,也可以从服务端收取信息。
MQTT主题:MQTT服务端在管理MQTT信息通讯时,就是使用“主题”来控制的。
MQTT通讯的核心是MQTT服务端,有了服务端对MQTT信息的接收、储存、处理和发送,客户端在发布和订阅信息时,可以相互独立,且在空间上可以分离,时间上可以异步。(特点:相互独立、空间可分离、时间可异步)
客户端订阅主题,服务端发布主题
MQTT服务端在管理MQTT信息通讯时,使用“主题”来控制。
注意:MQTT客户端在通讯时,往往角色不上单一的,它既可以作为信息发布者也可以同时作为信息订阅者。
相互独立:MQTT客户端是一个个独立的个体。它们无需了解彼此的存在,依然可以实现信息交流。比如以上实例中汽车客户端在发布“汽车速度”信息时,汽车客户端本身可以完全不知道有多少个MQTT客户端订阅了“汽车速度”这一主题。而订阅了“汽车速度”主题的手机和电脑客户端也完全不知道彼此的存在。大家只要订阅了“汽车速度”主题,MQTT服务端就会在每次收到新信息时,将信息发送给订阅了“汽车速度”主题的客户端。
空间可分离:MQTT客户端在通讯时必要条件是连接到了同一个MQTT通讯网络,这个网络可以是互联网或者局域网。只要客户端联网,无论他们远在天边还是近在眼前,都可以实现彼此间的通讯交流。
时间可异步:MQTT客户端在发送和接收信息时无需同步。这一特点对物联网设备尤为重要。有时物联网设备会发生意外离线的情况。我们使用以上实例二的场景来作为示例。当我们的汽车在行驶过程中,可能会突然进入隧道,这时汽车可能会断开与MQTT服务端的连接。假设在此时我们的手机客户端向汽车客户端所订阅的“空调温度”主题发布了信息,而汽车恰恰不在线。这时,MQTT服务端可以将“空调温度”主题的新信息保存,待汽车再次上线后,服务端再将“空调温度”信息推送给汽车。
连接MQTT服务端
MQTT客户端之间要想实现通讯,必须要通过MQTT服务端,因此MQTT客户端无论是发布信息还是订阅信息,首先都要连接MQTT服务端。
MQTT客户端连接服务器一共有两步:1.客户端向服务端发送连接请求;2.服务端向客户端发送连接确认。
MQTT客户端要想连接服务端,首先要向服务端发送connect报文(所谓报文就是一个MQTT数据包,这个 数据包中包含多个信息。),如果connect报文的格式或内容不符合MQTT规范,则服务器会拒绝客户端的连接请求。
connect报文所包含的信息:
- clientID 客户端ID,每个客户端的clientID是相互独立的
- cleanSession 清除会话,如果需要服务端保存重要报文,光设置cleanSession 为false是不够的,还需要传递的MQTT信息QoS级别大于0。对于不重要的MQTT客户端,它们在向服务器发送连接请求时,CONNECT报文中的cleanSession通常设置为true。原因是这类不重要的MQTT客户端即使丢失信息也不会影响整体系统运行。因此服务端在看到客户端的cleanSession为true时,就不会保存发送给它们的信息。
- keepAlive 心跳时间间隔,keepAlive用于服务端了解客户端连接情况
connack--确认连接请求
connack报文包括两个信息,一个是returncode(连接返回码),另一个是session pressent(当前会话)
返回码 | 返回码描述 |
---|---|
0 | 成功连接 |
1 | 连接被服务端拒绝,原因是不支持客户端的MQTT协议版本 |
2 | 连接被服务端拒绝,原因是不支持客户端标识符的编码。 可能造成此原因的是客户端标识符编码是UTF-8,但是服务端不允许使用此编码。 |
3 | 连接被服务端拒绝,原因是服务端不可用。 即,网络连接已经建立,但MQTT服务不可用。 |
4 | 连接被服务端拒绝,原因是用户名或密码无效。 |
5 | 连接被服务端拒绝,原因是客户端未被授权连接到此服务端。 |
sessionpresent--当前会话,当重要客户端连接服务端时,服务端可能保存着没有得到确认的报文。如果是这样的话,那么客户端在连接服务端时,就会通过sessionPresent来了解服务端是否有之前未能确认的信息。
如果connect报文中的cleanSession设置为true,这种情况下,客户端是不需要服务端保存任何报文的,那么服务端发送的确认连接connect报文中,sessionpresent肯定是false,也就是服务端没有保存任何报文。
CONNACK报文的sessionPresent与CONNECT报文的cleanSession相互配合。其作用是客户端发送连接请求时,服务端告知客户端有没有保存报文信息。
MQTT服务端连接操作
使用阿里云服务器,使用MQTTX调试工具
使用MQTTX进行连接之前,需要知道地址以及端口号等信息。
需要Broker Address,账号密码等都是通过他们进行获得。
Broker Address格式为:$ {ProductKey}.iot-as-mqtt.$ {region}.aliyuncs.com
使用MQTT.fx接入物联网平台 (aliyun.com)
参数 | 值 |
---|---|
ProductKey | a1*** |
DeviceName | device1 |
DeviceSecret | f35***d9e |
clientId | a1***.device1|securemode=2,signmethod=hmacsha256,timestamp=2524608000000| |
username | device1&a1*** |
passwd | 86761***21d |
mqttHostUrl | a1***.iot-as-mqtt.cn-shanghai.aliyuncs.com |
port | 1883 |
采用技小新MQTT工具进行配置。可以根据三元组信息生成MQTT需要连接的信息
- mqttClientId:格式中
| |
内为扩展参数。 - clientId:表示客户端ID,可自定义,长度不可超过64个字符。建议使用设备的MAC地址或SN码,方便您识别区分不同的客户端。
- securemode:表示目前安全模式,可选值有2(TLS直连模式)和3(TCP直连模式)。
- signmethod:表示签名算法类型。支持hmacmd5,hmacsha1和hmacsha256,默认为hmacmd5。
- timestamp:表示当前时间毫秒值,可以不传递。
- mqttPassword:sign签名需把提交给服务器的参数按字典排序后,根据signmethod加签。签名计算示例,请参见MQTT连接签名示例。
- content的值为提交给服务器的参数(productKey、deviceName、timestamp和clientId),按照参数名称首字母字典排序, 然后将参数值依次拼接。