基于MQTT 3.1版本,标准MQTT发布遗嘱消息的几种情况。
如果想设置遗嘱消息,那么客户端请求和代理服务器链接之前,必须把遗嘱消息提前填写好,在请求连接时,把遗嘱消息发给代理服务器。
MQTT遗嘱消息,什么时候订阅者会收到代理服务器发布的遗嘱消息?以下四种情况:
- 服务端发生了I/O 错误或者网络失败;
- 客户端在定义的心跳时期失联;
- 客户端在发送下线包之前关闭网络连接;
- 服务端在收到下线包之前关闭网络连接。
- 遗嘱标志 Will Flag
位置: 连接标志的第2位。
遗嘱标志( Will Flag) 被设置为1, 表示如果连接请求被接受了, 遗嘱( Will Message) 消息必须被存储在服务端并且与这个网络连接关联。 之后网络连接关闭时, 服务端必须发布这个遗嘱消息, 除非服务端收到DISCONNECT报文时删除了这个遗嘱消息。
遗嘱消息发布的条件, 包括但不限于:
- 服务端检测到了一个I/O错误或者网络故障。
- 客户端在保持连接( Keep Alive) 的时间内未能通讯。
- 客户端没有先发送DISCONNECT报文直接关闭了网络连接。
- 由于协议错误服务端关闭了网络连接。
如果遗嘱标志被设置为1, 连接标志中的Will QoS和Will Retain字段会被服务端用到, 同时有效载荷中必须包含Will Topic和Will Message字段。
一旦被发布或者服务端收到了客户端发送的DISCONNECT报文, 遗嘱消息就必须从存储的会话状态中移除。
如果遗嘱标志被设置为0, 连接标志中的Will QoS和Will Retain字段必须设置为0, 并且有效载荷中不能包含Will Topic和Will Message字段。
如果遗嘱标志被设置为0, 网络连接断开时, 不能发送遗嘱消息。
服务端应该迅速发布遗嘱消息。 在关机或故障的情况下, 服务端可以推迟遗嘱消息的发布直到之后的重启。 如果发生了这种情况, 在服务器故障和遗嘱消息被发布之间可能会有一个延迟。
- 遗嘱QoS Will QoS
位置: 连接标志的第4和第3位。
这两位用于指定发布遗嘱消息时使用的服务质量等级。
如果遗嘱标志被设置为0, 遗嘱QoS也必须设置为0(0x00)。
如果遗嘱标志被设置为1, 遗嘱QoS的值可以等于0(0x00), 1(0x01), 2(0x02)。 它的值不能是除此之外其他值。
- 遗嘱保留 Will Retain
位置: 连接标志的第5位。
如果遗嘱消息被发布时需要保留, 需要指定这一位的值。
如果遗嘱标志被设置为0, 遗嘱保留( Will Retain) 标志也必须设置为 0 。
如果遗嘱标志被设置为1:
- 如果遗嘱保留被设置为0, 服务端必须将遗嘱消息当作非保留消息发布。
- 如果遗嘱保留被设置为1, 服务端必须将遗嘱消息当作保留消息发布。
- 遗嘱主题 Will Topic
如果遗嘱标志被设置为1, 有效载荷的下一个字段是遗嘱主题( Will Topic) 。 遗嘱主题必须是1.5.3节定义的UTF-8编码字符串。
- 遗嘱消息 Will Message
如果遗嘱标志被设置为1, 有效载荷的下一个字段是遗嘱消息。 遗嘱消息定义了将被发布到遗嘱主题的应用消息, 这个字段由一个两字节的长度和遗嘱消息的有效载荷组成, 表示为零字节或多个字节序列。 长度给出了跟在后面的数据的字节数, 不包含长度字段本身占用的两个字节。
遗嘱消息被发布到遗嘱主题时, 它的有效载荷只包含这个字段的数据部分, 不包含开头的两个长度字节。
服务器端:
服务端实现可以监视客户端的行为, 检测潜在的安全风险。 例如:
- 重复的连接请求
- 重复的身份验证请求
- 连接的异常终止
- 主题扫描( 请求发送或订阅大量主题)
- 发送无法送达的消息( 没有订阅者的主题)
- 客户端连接但是不发送数据
发现违反安全规则的行为, 服务端实现可以断开客户端连接(MQTT服务器,可以添加其他对mqtt客户端限制的条件)。
服务端实现检测不受欢迎的行为, 可以基于IP地址或客户端标识符实现一个动态黑名单列表。
服务部署可以使用网络层次控制( 如果可用) 实现基于IP地址或其它信息的速率限制或黑名单。
遗嘱消息需要注意的点:
- 遗嘱Qos Will Qos
如果遗嘱标志设置为0,遗嘱的Qos也必须设置为0;
如果遗嘱标志设置为1,遗嘱的Qos可以等于0,1,2;
- 遗嘱保留Will Retain
如果遗嘱标志设置为0,遗嘱保留(Will Retain)标志位也必须设置为0;
如果遗嘱标志设置为1,分为两种:
如果遗嘱保留(Will Retain)设置为0,服务器必须将遗嘱消息当做非保留消息发布;
如果遗嘱保留(Will Retain)设置为1,服务器必须将遗嘱消息当做保留消息发布;
注意:
正常状态下发布者断开MQTT连接,正常关闭MQTT链路,设置的遗嘱消息是不会被代理服务器发布出去的。
软件设计时,需要检查参数个数,每个参数都需要判断,willretained,willqos,willtopic,willmessage,如果有一个参数设置超出范围,或者设置错误其他的参数都应该清空。不要产生参数“重影”,即有的参数设置错误,有的参数设置正确,应当防止这种情况的出现。