1. 参考文档:http://emqtt.com/docs/v2/mqtt.html#
官方中文文档:https://mcxiaoke.gitbooks.io/mqtt-cn/content/mqtt/01-Introduction.html
2. Topic:
Topic 通过’/’分割层级,支持’+’, ‘#’通配符:
'+': 表示通配一个层级,例如a/+,匹配a/x, a/y
'#': 表示通配多个层级,例如a/#,匹配a/x, a/b/c/d
发布者的topic不能使用通配符,订阅者可以订阅多个主题,通配符的目的就是在订阅方使用
3.QoS
按消息质量由低到高 分为:0 1 2
这个质量体现在 发布者 到 Broker 和 Broker 到 订阅者 2种消息质量
3.1 发布者(A) 到 Broker(B) :
0:A 只发送一次到 B,A和B都不会存储消息(发送消息可能出现异常,即发即弃,所以broker可能由于异常而没收到信息)
接收次数 <= 1
1:至少发送一次,A和B都会存储消息(A一定时间(read的timeout)内没收到B返回的PUBACK就会重新发送,收到就会删除消息;B收到消息会存储消息(由于B存储消息,所以收到多个重复消息也能根据消息id去除重复消息) )
接收次数 >= 1
2:确保每个消息只会被接收到一次 ,A B都会存储消息
接收次数 = 1
Qos 如果保证每个消息不会重复送到且只会被接收到一次?
过程: 发布者 A 和 Broker B , 消息内容
1 A 持久化消息,然后重复发送消息直到收到PUBREC信息
2 B 持久化消息,存储PUBREC信息,重复返回 PUBREC 直到 收到 PUBREL
3 A 收到PUBREC信息,删除消息,保存 PacketID,发送PUBREL
4 B 收到PUBREL(B可能收到多个PUBREL,但此时已影响不大),删除PUBREC信息,返回PUBCOMP A 删除PacketID,此消息在A彻底结束了(A有可能没收到PUBCOMP)
解读:
正常情况共4次消息: A发送消息 B发送PUBREC A删除消息发送PUBREL B发送PUBCOMP
注意:B最后发送PUBCOMP,也不确定A是否收到了,所以最后可能A还在发PUBREL继续等待返回PUBCOMP。但是此时已经确定的是:A删除了消息,且B收到并存储了消息,后续的消息回复已经不需要保证了,否则可以一直无限循环下去(TCP三次握手也是一样的逻辑,发送消息 -- 你知道我收到了么 -- 我知道你收到了,你知道我知道你收到了么--......)。
为什么不是前1次消息:A不确定 消息 是否发送给了B (qos = 0的缺点 <=1 )
为什么不是前2次消息:B不确定 是否 A删除了消息 (qos =1 的缺点,B接收次数>=1)
为什么不是前3次消息:A不确定 B是否 知道A已经删除了消息(为什么要A删除消息,B不是会过滤重复消息么?这是因为怕B把 消息发送给订阅者后删除消息,而此时A又发了一条消息给B,这样在B的消息队列里面这又是一条新的消息。这也是Qos=1时会有重复消息,在Qos=1中,B发送PUBACK如果A没收到,如果B中消息没有删除,那A继续发给B,B也不会存重复,但如果A发给B时,B已经删除这条消息(发给订阅者后删除了消息),那B又会重新把这条消息存储下来)
也就是说保证AB之间接收消息 =1的 关键是B收到消息后并且收到A已删除的消息
Connect时可设置:
cleanSession:发布和订阅 topic 时指定(发布者订阅者:客户端; Broker:服务端 )
0/false: 断开连接时,session 里保存着发送一半的数据(未确认的数据)和 需要发往这个session的数据
客户端:
发布者发送给服务器,但是还没有完成确认的QoS 1(没收到PUBACK,重发PUBLISH)和QoS 2级别的消息;
订阅者接收服务器,但是还没有完成确认的QoS 2级别的消息;
服务端:(包括发送一半的消息和还没发送的消息)
Qos1中:发给订阅者但没有收到PUBACK
Qos2中:发给订阅者但没确定的消息,发给发布者但没确定的消息
还没有发送给 订阅者的消息
1/true: 每次 客户端和服务端连接都是 一个新的session(收不到没连接前的旧消息)
注:
1 这个Session在客户端会存在,在服务端会存在对应的2种Session(与某个发布者的Session,与某个订阅者的Session)
2 Session会至少持续到有效的网络连接(断网就会删除,是保存在内存里,程序关闭也会清除)
3 如果要清除服务端的某个0的Session,需要客户端设置cleanSession为1后连上该Session再disconnect
4 要确保一定收到在线消息和离线消息,需要设置Qos为1/2,cleanSession为flase/0
Will (遗嘱消息):发布或订阅者连接时可以发布Will至服务器存储
Will消息发布条件:(非主动disconnect的情况),收到了客户端发送的DISCONNECT报文,遗嘱消息删除
1 服务端检测到IO错误或网路故障
2 在发送心跳包时,keepAlive时间内没收到通讯
3 客户端没有先发送DISCONNECT报文直接关闭了网络连接
4 由于协议错误服务端关闭了网络连接
keepAlive(以秒为单位):
1 客户端发送PINGREQ报文,如果在keepAlive内没收到 服务端的的PINGRESP报文,就会断开连接。
2 服务端在1.5倍KeepAlive时间内没有收到 客户端的PINGREQ报文,也会主动断开连接
3 设为0表示关闭keepAlive,客户端不会发送心跳包