序
在MQTT協(xié)議中,最重要的就是發(fā)布/訂閱,下面重點(diǎn)分析下消息訂閱。
SUBSCRIBE
一般來(lái)講,客戶(hù)端在成功建立TCP連接之后,發(fā)送CONNECT消息,在得到服務(wù)器端授權(quán)允許建立彼此連接的CONNACK消息之后,客戶(hù)端會(huì)發(fā)送SUBSCRIBE消息,訂閱感興趣的Topic主題列表(至少一個(gè)主題),一個(gè)完整示范如下:

固定頭部
Qos Level,可根據(jù)實(shí)際情況進(jìn)行調(diào)整為0/1/2等。一般設(shè)為0表示最多一次??蛻?hù)端可設(shè)置OoS Level值。 DUP flag,值為0表示第一次發(fā)送。
可變頭部
因?yàn)樯厦媸痉禥oS level值為1,因此需要客戶(hù)端傳遞消息ID,16位,無(wú)符號(hào)的short類(lèi)型。
消息體
訂閱的主題名稱(chēng)采用修改版UTF-8編碼,然后緊跟著對(duì)應(yīng)的QoS值。下面的次序,可能更為形象:
| Topic name | "a/b" |
|---|---|
| Requested QoS | 1 |
| Topic name | "c/d" |
| Requested QoS | 2 |
訂閱者的Topic name支持通配符#和+ :
- #支持一個(gè)主題內(nèi)任意級(jí)別話題
- +只匹配一個(gè)主題級(jí)別的通配符
eg:
finance/stock/#
finance/sotkc/ibm/+
都是有效,更具體規(guī)則,請(qǐng)參閱協(xié)議附加部分。
在服務(wù)器接收處理時(shí),按照順序讀取即可:
String topicName = readUTF();
int qosVal = read();
服務(wù)器可以發(fā)送QoS不大于客戶(hù)端設(shè)置OoS的消息,尤其是服務(wù)器不提供良好的持久化機(jī)制的時(shí)候。
SUBACK
服務(wù)器會(huì)對(duì)發(fā)出SUBSCRIBE的消息返回一個(gè)確認(rèn)消息。

可變頭部
Message Identifier,服務(wù)器需要附加,客戶(hù)端需要處理。
消息體
QoS,為服務(wù)器根據(jù)實(shí)際情況授予的QoS級(jí)別列表,和客戶(hù)端發(fā)送的SUBSCRIBE的訂閱Topic Name順序完全一致。
客戶(hù)端訂閱幾個(gè)TOPIC,服務(wù)器端一一給出各個(gè)TOPIC的QoS具體值。
UNSUBSCRIBE
服務(wù)器需要支持客戶(hù)端取消訂閱功能,UNSUBSCRIBE消息格式和SUBSCRIBE消息格式差不多,除了消息類(lèi)型不同,消息體中沒(méi)有了QoS字節(jié),其它沒(méi)有區(qū)別。

可變頭部的消息ID的出現(xiàn)還是由固定頭部的QoS Level(1)決定是否存在。
一般來(lái)講,客戶(hù)端發(fā)布退訂,服務(wù)器端需要返回退訂確認(rèn)。
MQTT沒(méi)講是否允許客戶(hù)端退訂所有TOPIC。
UNSUBACK
服務(wù)器返回的UNSUBSCRIBE消息UNSUBACK相應(yīng)很簡(jiǎn)單,沒(méi)有消息體。

小結(jié)
訂閱部分,共有四個(gè)消息,分別一一對(duì)應(yīng)。
| 命令 | 響應(yīng) | 備注 | 建議 |
|---|---|---|---|
| SUBSCRIBE | SUBACK | 協(xié)議沒(méi)有涉及最多運(yùn)行訂閱TOPIC數(shù)目,隱藏的隱患 | 建議至多10個(gè) |
| UNSUBSCRIBE | UNSUBACK | 是否可以退訂所有訂閱,不詳 | 建議保留至少一個(gè)Topic |