Publish报文及其响应分析

PUBLISH报文及其响应

PUBLISH控制报文是指从Client端向Broker端或者Broker端向Client端传输一个应用消息,用于消息的发布。在这里插入图片描述

PUBLISH报文头的第一个字节中,bit2和bit1用于设置QoS级别,可设置为0,1,2。MQTT协议规定,PUBLISH报文根据不同的QoS级别,其报文响应机制不同,如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ezyAj0L9-1590393201757)(C:\Users\ThinkPad\AppData\Roaming\Typora\typora-user-images\image-20200521101412930.png)]

固定报头

如下表格描述了PUBLISH报文固定报头格式。

字段描述
byte1bit7-bit4:MQTT控制报文类型 bit3: DUP bit2-bit1:QoS级别 bit0:RETAIN
byte2…剩余长度

重发标志DUP

如果DUP被设置为0,表示这是Clinet端或者Broker端第一次请求发送这个报文。如果DUP被设置为1,表示这可能是一个报文请求的重发。

Client端或Broker端请求重发一个PUBLISH报文时,必须将DUP标志设置为1.对于QoS为0的报文,DUP标志必须设置为0.

Broker端发送PUBLISH报文给订阅者时,收到的PUBLISH报文的DUP标志的值不会被传播。Client发送的PUBLISH和收到的PUBLISH中的DUP标志是独立设置的,没有互相关系,其值必须单独的根据发送的PUBLISH报文是否是一个重发来确定。

QoS服务质量等级

QoS字段表示应用消息分发的服务质量等级。如下表格所示

QoSbit2bit1描述
000最多分发一次
101至少分发一次
210只分发一次
-11保留

PUBLISH报文不能将QoS所有的位都设为1。如果收到的QoS所有位都为1,必须关闭网络连接。

RETAIN保留保留标志位

如果Client端发送给Broker端的PUBLISH报文的RETAIN位被设置为1,Broker端必须存储这个应用消息和它的QoS,以便可以分发给未来的主题名匹配的订阅者。一个新的订阅创建时,对每个匹配的主题名,如果存在最近保留的消息,它必须被发送给订阅者。如果Broker端收到一条保留标志为1的QoS0消息,它必须丢弃之前为那个主题保留的任何消息,并且应该将这个新的QoS0消息当做那个主题的新的保留消息,但是任何时候都可以选择丢弃它,如果这种情况发生了,那么该主题将没有保留消息。

Broker端发送PUBLISH报文给Clinet端时,如果消息是作为Client端一个新订阅的结果发送,必须将报文的保留标志位设为1。当一个PUBLISH报文发送给Client端是因为匹配一个已建立的订阅时,Broker端必须将保留标志位设为0,不管它收到的这个消息中保留标志的值是多少。

保留标志位为1,有效载荷为零字节的PUBLISH报文会被Broker端当作正常消息处理,它会被发送给订阅主题匹配的Client端。此外,同一个主题下任何现存的保留信息必须被移除,因此这个主题之后的任何订阅者都不会受到一个保留信息。
保留标志为1且有效载荷为零字节的PUBLISH报文会被Broker端“当作正常”消息处理,它会被发送给订阅主题匹配的Client端。此外,同一个主题下任何现存的保留消息必须被移除,因此这个主题之后的任何订阅者都不会收到一个保留消息 。“当作正常”意思是现存的Client端收到的消息中保留标志未被设置。Broker端不能存储零字节的保留消息 。如果Client端发给Broker端的PUBLISH报文的保留标志位0,Broker端不能存储这个消息也不能移除或替换任何现存的保留消息 。

如果Client端发给Broker端的PUBLISH报文的保留标志位0,Broker端不能存储这个消息也不能移除或替换任何现存的保留消息。

剩余长度

等于可变报头的长度加上有效载荷的长度。

可变报头

可变报头组成如下表所示:

字段描述
Topic Name主题名例如:a,b, temperature
Packet Identifier报文标识符10

主题名

主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。
主题名必须是PUBLISH报文可变报头的第一个字段,必须是 UTF-8编码的字符串,且不能 包含通配符。
Broker端发送给订阅Client端的PUBLISH报文的主题名必须匹配该订阅的主题过滤器。

报文标识符

只有当QoS等级是1或2时,报文标识符(Packet Identifier)字段才能出现在PUBLISH报文中,可以参考《MQTT报文分析》。

有效载荷

有效载荷包含将被发布的应用消息。数据的内容和格式是应用特定的。有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的PUBLISH报文是合法的。

动作 Actions

Client端使用PUBLISH报文发送应用消息给Broker端,目的是分发到其它订阅匹配的Client端。
Broker端使用PUBLISH报文发送应用消息给每一个订阅匹配的Client端。

Client端使用带通配符的主题过滤器请求订阅时,Client端的订阅可能会重复,因此发布的消息可能会匹配多个过滤器。对于这种情况,Broker端必须将消息分发给所有订阅匹配的QoS等级最高的Client端 。Broker端之后可以按照订阅的QoS等级,分发消息的副本给每一个匹配的订阅者。

收到一个PUBLISH报文时,接收者的动作取决于QoS等级。如果Broker端实现不授权某个Client端发布PUBLISH报文,它没有办法通知那个Client端。它必须按照正常的QoS规则发送一个正面的确认,或者关闭网络连接。

PUBACK-发布确认

PUBACK报文是对QoS 1等级的PUBLISH报文的响应,其组成如下图所示

字段描述
固定报头2字节
可变报头2字节

固定报头

固定报头如下表所示

字段描述
byte1bit7-bit4:MQTT报文类型 bit3-bit0:保留位
byte2剩余长度:PUBACK报文头这个值为0x02

可变报头

可变报头如下表所示

字段描述
byte1报文标识符MSB
byte2报文标识符LSB

动作

参考后续文章,MQTT协议的操作行为

PUBREC – 发布收到(QoS 2,第一步)

PUBREC报文是对QoS等级2的PUBLISH报文的响应,它是QoS 2等级协议交换的第二个报文,其组成如下表所示:

字段描述
固定报头2字节
可变报头2字节

固定报头

固定报头如下表所示

字段描述
byte1bit7-bit4:MQTT报文类型 bit3-bit0:保留位
byte2剩余长度:PUBREC报文头这个值为0x02

可变报头

可变报头如下表所示

字段描述
byte1报文标识符MSB
byte2报文标识符LSB

动作

参考后续文章,MQTT协议的操作行为

PUBREL – 发布释放(QoS 2,第二步)

PUBREL报文是对PUBREC报文的响应。它是QoS 2等级协议交换的第三个报文,其组成如下所示:

字段描述
固定报头2字节
可变报头2字节

固定报头

固定报头如下表所示:

字段描述
byte1bit7-bit4:MQTT报文类型 bit3-bit0:保留位,必须设置为0010
byte2剩余长度:PUBREL报文头这个值为0x02

可变报头

可变报头如下表所示

字段描述
byte1报文标识符MSB
byte2报文标识符LSB

动作

参考后续文章,MQTT协议的操作行为

PUBCOMP – 发布完成(QoS 2,第三步)

PUBCOMP报文是对PUBREL报文的响应。它是QoS 2等级协议交换的第四个也是最后一个报文,其组成如下表所示:

字段描述
固定报头2字节
可变报头2字节

固定报头

固定报头如下表所示

字段描述
byte1bit7-bit4:MQTT报文类型 bit3-bit0:保留位
byte2剩余长度:PUBCOMP报文头这个值为0x02

可变报头

可变报头如下表所示

字段描述
byte1报文标识符MSB
byte2报文标识符LSB

动作

参考后续文章,MQTT协议的操作行为

引用

1 《MQTT协议中文版本》:https://mcxiaoke.gitbooks.io/mqtt-cn/content/

可变报头如下表所示

字段描述
byte1报文标识符MSB
byte2报文标识符LSB

动作

参考后续文章,MQTT协议的操作行为

引用

1 《MQTT协议中文版本》:https://mcxiaoke.gitbooks.io/mqtt-cn/content/

2 《MQTT Version 3.1.1》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是Python实现PUBLISH和PUBACK的示例代码,用于客户端将消息发布到指定的Topic: ```python import struct # 构建PUBLISH def build_publish_packet(topic, message, qos, packet_id=None): packet_type = 0x30 # PUBLISH类型 remaining_length = 2 + len(topic) + len(message) # 剩余长度 if qos > 0: remaining_length += 2 # 构建payload数据 payload = topic.encode('utf-8') + message.encode('utf-8') if qos > 0: payload = struct.pack("!H", packet_id) + payload # 构建固定头 fixed_header = struct.pack("!B", packet_type | ((qos & 0x03) << 1)) return fixed_header + encode_remaining_length(remaining_length) + payload # 构建PUBACK def build_puback_packet(packet_id): packet_type = 0x40 # PUBACK类型 remaining_length = 2 # 剩余长度 # 构建payload数据 payload = struct.pack("!H", packet_id) # 构建固定头 fixed_header = struct.pack("!B", packet_type) return fixed_header + encode_remaining_length(remaining_length) + payload # 编码剩余长度 def encode_remaining_length(length): remaining_length = bytearray() while length > 0: digit = length % 128 length //= 128 if length > 0: digit |= 0x80 remaining_length.append(digit) return remaining_length # 测试代码 topic = "test/topic" message = "Hello, MQTT!" qos = 1 packet_id = 1 publish_packet = build_publish_packet(topic, message, qos, packet_id) print("PUBLISH:", publish_packet.hex()) puback_packet = build_puback_packet(packet_id) print("PUBACK:", puback_packet.hex()) ``` 上述代码中,`build_publish_packet()`函数用于构建PUBLISH,需要传入发布的主题、消息、QoS等级和标识符(如果QoS大于0)。`build_puback_packet()`函数用于构建PUBACK,需要传入标识符。 需要注意的是,MQTT协议中支持不同的QoS等级,具体可以参考MQTT协议档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值