专业IM即时通讯软件开发,值得信赖!

MQTT-SN协议乱翻之消息格式

MQTT 云聊IM 958℃

前言

紧接着上篇初步介绍,本文为第二篇,主要梳理MQTT-SN 1.2协议中定义的消息格式。

通用消息格式

消息头部

  1. 长度要么是1个字节,要么3个字节表示,并且自身也会包含在其内。一个字节可表示256长度,一般情况下,完全够用了。
  2. 只需要判断第一个字节是否为 0x01,若是那么长度为3个字节表示,剩下的两个字节会表示真正的消息长度,最大长度为65535
  3. 否则长度就是一个字节表示,256个长度,大部分消息长度都是一个字节,除非特别提醒

备注:

MQTT-SN不支持消息的分片和重组。底层网络所定义数据包长度若小于MQTT-SN消息的最大长度,自身进行的分片和重组,对MQTT-SN协议本身不受影响。

MQTT-SN消息类型

MQTT-SN定义的消息类型数量众多,超过25个,感觉有些头大。

消息可变部分

可变字段很多,与MQTT相比,多了:

  1. 持续时长字段(Duration)
  2. 标识符Flags有所不同,下面表格进行说明
  3. 网关地址(GwAdd),可变长度,但依赖于底层网络,在ZigBee网络中2个字节长度
  4. 一个字节网关Id(GwId)
  5. 协议Id(ProtocolId),一个字节,唯一值 0x01,统一表示协议名称和协议名称
  6. 广播路径跳数(广播路径深度/广播辐射范围),Radius,一个字节表示,0x00表示广播给当前网络中所有节点
  7. CONNECT/REGISTER/SUBSCRIBE/PUBLISH等消息对应回执中都会包含返回码Recode Code,见下表格

消息可变部分

可变字段很多,与MQTT相比,多了:

  1. 持续时长字段(Duration)
  2. 标识符Flags有所不同,下面表格进行说明
  3. 网关地址(GwAdd),可变长度,但依赖于底层网络,在ZigBee网络中2个字节长度
  4. 一个字节网关Id(GwId)
  5. 协议Id(ProtocolId),一个字节,唯一值 0x01,统一表示协议名称和协议名称
  6. 广播路径跳数(广播路径深度/广播辐射范围),Radius,一个字节表示,0x00表示广播给当前网络中所有节点
  7. CONNECT/REGISTER/SUBSCRIBE/PUBLISH等消息对应回执中都会包含返回码Recode Code,见下表格

具体消息格式说明

ADVERTISE

网关周期性会对当前网络下所有客户端、节点进行广播,用于客户端发现可用网关。

SEARCHGW

客户端主动寻找网关进行广播的消息,广播路径范围受限于当前网络环境下的客户端部署密度,比如只有1跳广播在非常密集的网络环境下客户端都可以彼此互相访问。

GWINFO

GWINFO作为对SEARCHGW消息的响应:

  1. 若由网关发出,则无GwAdd字段
  2. 若来自于客户端,需要包含网关地址

CONNECT

客户端向网关发出建立连接的消息。

在CONNECT消息标志位具体表示如下:

  1. 0/1 表示具体值待定
  2. X 表示没有使用到

在Flags中使用到的标志位:

  1. Will:若为1,客户端会在稍后请求遗嘱主题和遗嘱消息
  2. CleanSession:不但表示订阅持久化,同时也被可扩展到遗嘱主题和遗嘱消息中

CONNACK

网关对客户端发出CONNECT消息的响应。

WILLTOPICREQ

根据客户端CONNECT标志位中WILL字段为true情况下,网关向客户端发出遗嘱主题请求,格式如下:

只有头部部分,很简单。

WILLTOPIC

客户端作为网关WILLTOPICREQ请求响应消息。下面是一个正常版本的WILLTOPIC消息:

此时的标志位如下

而空的WILLTOPIC也是允许存在的,就两个字节表示,用于客户端请求删除已存在于服务器端的对应遗嘱主题和消息。

WILLMSGREQ

根据客户端CONNECT标志位中WILL字段为真情况下,网关向客户端发出遗嘱消息请求,格式如下:

只有头部部分,没有别的。

WILLMSG

客户端对网关WILLMSGREQ请求的响应,从而把遗嘱消息传递给网关进行保存。

REGISTER

  1. 客户端–>网关,请求主题(topic name)对应的主题标识符(topic id)
  2. 网关–>客户端,通知主题(topic name)已经被指派到某个主题标识符(topic id)

REGACK

客户端或网关针对REGISTER消息的响应。

PUBLISH

PUBLISH消息用于客户端或网关发布消息用:

标识位具体如下:

标识位里面各个字段和MQTT协议一致,无须多解释。

PUBACK

客户端/网关仅仅对QoS 1/2的PUBLISH消息做出响应。

处理PUBLISH消息异常?在PUBACK消息中的ReturnCode字段中以相应值体现出来,这就要求接收者处理拒绝理由。

PUBREC, PUBREL, PUBCOMP

只有在PUBLISH消息中QoS 2时,PUBREC, PUBREL, PUBCOMP才会一起登场,否则是没有出场机会的。消息格式嘛,都很统一:

SUBSCRIBE

SUBSCRIBE用于客户端订阅某个主题的消息。

标识位具体如下:

此处,标志位中TopicIdType决定了SUBSCRIBE消息中TopicId/TopicName字段具体填充值:预定义topic id,或短小两个字符表示主题(topic name),或直接填写主题。

SUBACK

网关->客户端,订阅处理情况的确认回执,接受订阅或出于其它原因拒绝之。

标识位具体如下:

SUBACK消息标志位中QoS为网关根据实际情况授权后的QoS具体值,这也应该是客户端需要知道并处理的。

UNSUBSCRIBE

UNSUBSCRIBE用于客户端取消订阅某个主题的消息。

标识位具体如下:

UNSUBSCRIBE消息标志位中唯一可用属性TopicIdType决定了UNSUBSCRIBE消息中TopicId/TopicName字段具体填充值。

UNSUBACK

网关->客户端,取消订阅处理情况的确认回执,很简单,4个字节表示。

PINGREQ

和MQTT协议中的PINGREQ一致,存活检测。

PINGRESP

接受PINGREQ消息的一方,如网关响应PINGRESP消息表示自己现在运行OK。

另外一个意图,若唤醒状态客户端发送PINGREQ消息之后,直接收到PINGRESP消息,表示网关当前暂时没有为其缓存的消息可供发送。

很简单,两个字节表示足矣。

DISCONNECT

  1. 客户端->网关,客户端主动关闭当前连接,网关响应确认消息。只有表示自己进入睡眠状态的客户端,才会在DISCONNECT消息中附加Duration持续字段。
  2. 网关->客户端,网关由于异常主动通知客户端关闭两者之间连接,客户端接收到DISCONNECT时需要发送CONNECT消息到网关,重试重新建立连接。没有Duration字段填充。

网关接收到要进入休眠状态的客户端发送的包含有Duration字段DISCONNECT消息时,可以直接返回2个字节的(不能包含有Duration字段)DISCONNECT消息以示确认。

WILLTOPICUPD

客户端发送请求网关更新其遗嘱主题。

标识位具体如下:

协议规定只有两个字节空WILLTOPICUPD也是允许存在的,存在意义用于客户端请求网关删除已保存的遗嘱主题和遗嘱消息等。

WILLTOPICRESP

WILLTOPICRESP为网关收到WILLTOPICUPD后作出的应答消息。

WILLMSGUPD

客户端->网关,确认更新的遗嘱消息。

WILLMSGRESP

WILLMSGRESP为网关收到WILLMSGUPD后作出的应答消息。

转发封装

在MQTT-SN架构图中,MQTT-SN Forwarder转发器适用于客户端无法直接访问网关或当前传感器网络区域中不存在网关时,转发器作用就体现出来了:

  1. 接收MQTT-SN客户端消息封装后转发给上游网关
  2. 解封上游网关所发送消息,直接发送给对应客户端

转发器作用于消息的封装转发,解封发送,针对消息不做修改。

转发器对MQTT-SN消息封装格式:

无线节点Id(Wireless Node Id):

  1. 转发器->网关,无线节点Id为转发器所在的无线节点Id,便于告知网关转发器位置
  2. 网关->转发器,无线节点Id为网关的无线节点Id

控制交换字段Ctrl,单个字节,位表示含义:

小结

MQTT-SN 1.2规范中所定义消息格式介绍完毕,下一篇将对MQTT-SN主要流程功、能进行阐述。

喜欢 (0)
仿微信聊天软件开发
点击这里给我发消息