我是靠谱客的博主 怕黑台灯,最近开发中收集的这篇文章主要介绍MQTT协议分析总结(一)相关文章1.前言2.MQTT协议实现方式3.MQTT 控制报文格式4.MQTT 控制报文5.参考资料,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 相关文章
  • 1.前言
  • 2.MQTT协议实现方式
  • 3.MQTT 控制报文格式
      • 3.1 固定报头的格式
      • 3.2 可变报头
      • 3.3 有效载荷 Payload
  • 4.MQTT 控制报文
  • 5.参考资料

相关文章

1.《MQTT协议分析总结(一)》
2.《MQTT协议分析总结(二)》
3.《【IoT】如何连接到百度IoT云》
4.《【FreeRTOS】基于STM32移植LWIP 2.1.2之MQTT》

1.前言

MQTT 3 (当前版本3.1.1)是目前使用的最为广泛的MQTT协议标准。尽管MQTT 5标准已经发布,并且带来了一些令人振奋的新特性,但是在整个应用场景上,业界从版本 35 的过渡可能会持续一段时间。MQTT最大的优点在于可以以极少的代码和有限的带宽,为远程设备提供实时可靠的消息服务。做为一种低开销、低带宽占用的即时通讯协议,MQTT在物联网、小型设备、移动应用等方面有广泛的应用。

2.MQTT协议实现方式

实现MQTT协议需要客户端服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)代理(Broker 服务器)订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。

MQTT传输的消息分为:主题(Topic)负载(payload)两部分:

  • (1)Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload)
  • (2)payload,可以理解为消息的内容,是指订阅者具体要使用的内容
    在这里插入图片描述

3.MQTT 控制报文格式

MQTT协议工作在TCP之上,端和代理之间通过交换预先定义的控制报文来完成通信。MQTT报文有 3 个部分组成,并按下表顺序出现:

Fixed header固定报头,所有控制报文都包含
Variable header可变报头,部分控制报文包含
Payload有效载荷,部分控制报文包含

3.1 固定报头的格式

Bit76543210
byte 1MQTT控制报文的类型用于指定控制报文类型的标志位
byte 2...剩余长度
  • MQTT控制报文的类型
名字报文流动方向描述
Reserved0禁止保留
CONNECT1客户端到服务端客户端请求连接服务端
CONNACK2服务端到客户端连接报文确认
PUBLISH3两个方向都允许发布消息
PUBACK4两个方向都允许QoS 1消息发布收到确认
PUBREC5两个方向都允许发布收到(保证交付第一步)
PUBREL6两个方向都允许发布释放(保证交付第二步)
PUBCOMP7两个方向都允许QoS 2消息发布完成(保证交互第三步)
SUBSCRIBE8客户端到服务端客户端订阅请求
SUBACK9服务端到客户端订阅请求报文确认
UNSUBSCRIBE10客户端到服务端客户端取消订阅请求
UNSUBACK11服务端到客户端取消订阅报文确认
PINGREQ12客户端到服务端心跳请求
PINGRESP13服务端到客户端心跳响应
DISCONNECT14客户端到服务端客户端断开连接
Reserved15禁止保留
  • 剩余长度
    位置: 从第2个字节开始。

    剩余长度(Remaining Length) 表示当前报文剩余部分的字节数,包括可变报头负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。

    剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码。更大的值按下面的方式处理。低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码128个数值和一个延续位(continuation bit)剩余长度字段最大4个字节

字节数最小值最大值
10 (0x00)127 (0x7F)
2128 (0x80, 0x01)16 383 (0xFF, 0x7F)
316 384 (0x80, 0x80, 0x01)2 097 151 (0xFF, 0xFF, 0x7F)
42 097 152 (0x80, 0x80, 0x80, 0x01)268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

分别表示(每个字节的低7位用于编码数据,最高位是标志位):

  • 1个字节时,从0(0x00)到127(0x7f)
  • 2个字节时,从128(0x80,0x01)到16383(0Xff,0x7f)
  • 3个字节时,从16384(0x80,0x80,0x01)到2097151(0xFF,0xFF,0x7F)
  • 4个字节时,从2097152(0x80,0x80,0x80,0x01)到268435455(0xFF,0xFF,0xFF,0x7F)

非负整数X使用 变长编码方案 的算法如下:

   do
  encodedByte = X MOD 128
  X = X DIV 128
 // if there are more data to encode, set the top bit of this byte
 if ( X > 0 )
     encodedByte = encodedByte OR 128
 endif
     'output' encodedByte
while ( X > 0 )

MOD是模运算,DIV是整数除法,OR是位操作或(C语言中分别是%,/,|)

对应的C语言代码如下:

/**
 * Encodes the message length according to the MQTT algorithm
 * @param buf the buffer into which the encoded data is written
 * @param length the length to be encoded
 * @return the number of bytes written to buffer
 */
int MQTTPacket_encode(unsigned char* buf, int length)
{
	int rc = 0;

	FUNC_ENTRY;
	do
	{
		char d = length % 128;
		length /= 128;
		/* if there are more digits to encode, set the top bit of this digit */
		if (length > 0)
			d |= 0x80;
		buf[rc++] = d;
	} while (length > 0);
	FUNC_EXIT_RC(rc);
	return rc;
}

剩余长度字段的 变长解码方案 算法如下:

multiplier = 1
value = 0
do
      encodedByte = 'next byte from stream'
      value += (encodedByte AND 127) * multiplier
      if (multiplier > 128*128*128)
        throw Error(Malformed Remaining Length)
      multiplier *= 128
while ((encodedByte AND 128) != 0)

AND是位操作与(C语言中的&)
这个算法终止时,value包含的就是剩余长度的值。

对应的C语言代码如下:

/**
 * Decodes the message length according to the MQTT algorithm
 * @param getcharfn pointer to function to read the next character from the data source
 * @param value the decoded length returned
 * @return the number of bytes read from the socket
 */
int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
{
	unsigned char c;
	int multiplier = 1;
	int len = 0;
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4

	FUNC_ENTRY;
	*value = 0;
	do
	{
		int rc = MQTTPACKET_READ_ERROR;

		if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
		{
			rc = MQTTPACKET_READ_ERROR;	/* bad data */
			goto exit;
		}
		rc = (*getcharfn)(&c, 1);
		if (rc != 1)
			goto exit;
		*value += (c & 127) * multiplier;
		multiplier *= 128;
	} while ((c & 128) != 0);
exit:
	FUNC_EXIT_RC(len);
	return len;
}

3.2 可变报头

某些MQTT控制报文包含一个可变报头部分。它在固定报头和负载之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。

备注:可变报头不仅指报文标识符,下面只是用它来举例。MQTT 报文类型的不同,就有不同的可变报头。

报文标识符字节,如下:

Bit7 - 0
byte 1报文标识符 MSB
byte 2报文标识符 LSB

很多控制报文的可变报头部分包含一个两字节的报文标识符字段。需要报文标识符的控制报文在下面的表格中列出:

控制报文报文标识符字段
CONNECT不需要
CONNACK不需要
PUBLISH需要(如果QoS > 0)
PUBACK需要
PUBREC需要
PUBREL需要
PUBCOMP需要
SUBSCRIBE需要
SUBACK需要
UNSUBSCRIBE需要
UNSUBACK需要
PINGREQ不需要
PINGRESP不需要
DISCONNECT不需要

客户端服务端彼此独立地分配报文标识符。因此,客户端服务端组合使用相同的报文标识符可以实现并发的消息交换。举例如下:
在这里插入图片描述
在这里插入图片描述

3.3 有效载荷 Payload

某些MQTT控制报文在报文的最后部分包含一个有效载荷,对于PUBLISH来说有效载荷就是应用消息。

有效载荷的控制报文 Control Packets that contain a Payload

控制报文有效载荷
CONNECT需要
CONNACK不需要
PUBLISH可选
PUBACK不需要
PUBREC不需要
PUBREL不需要
PUBCOMP不需要
SUBSCRIBE需要
SUBACK需要
UNSUBSCRIBE需要
UNSUBACK不需要
PINGREQ不需要
PINGRESP不需要
DISCONNECT不需要

4.MQTT 控制报文

具体的每个报文在下面的文章中介绍:《MQTT协议分析总结(二)》

5.参考资料

MQTT 5.0协议中文版:
https://github.com/twoFiveOneTen/MQTT_V5
MQTT Version 5.0:
http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02.htm
MQTT 3.1.1协议中文版:
https://github.com/mcxiaoke/mqtt
MQTT Version 3.1.1:
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

最后

以上就是怕黑台灯为你收集整理的MQTT协议分析总结(一)相关文章1.前言2.MQTT协议实现方式3.MQTT 控制报文格式4.MQTT 控制报文5.参考资料的全部内容,希望文章能够帮你解决MQTT协议分析总结(一)相关文章1.前言2.MQTT协议实现方式3.MQTT 控制报文格式4.MQTT 控制报文5.参考资料所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部