前言:
前一篇提到MQTT有很多種Message Type用來實現協定。
而這次會特別把CONNECT Message拿出來講,主要是因為在CONNECT Message裡面有用到了許多的flag,而這些flag又會跟MQTT的一些特性有關,因此有必要將之獨立出來說明。
Message Format
在開始談CONNECT message之前,讓我們先來看看MQTT的訊息格式。 MQTT的訊息格式如下圖所示:
其中:
- Fixed Header每個類型的訊息都會有,至少為2 byte。
- Variable Header會根據訊息類型而有所不同,某些訊息類型甚至沒有variable header。
- Payload和Variable Header一樣,也會根據訊息類型不同而有所不同,某些訊息類型沒有Payload。
CONNECT Message
接著讓我們來看看今天的主角CONNECT Message,首先先看看它的Fixed Header。
Fixed Header:
bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
byte 1 | Message Type(1) | DUP flag | QoS level | RETAIN | ||||
0 | 0 | 0 | 1 | x | x | x | x | |
byte 2 | Remaining Length |
在CONNECT Message裡面,fixed header並不會用到太多欄位,因此這邊只會簡單介紹一下他們。
Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是CONNECT Message的關係,因此會填上0001。
DUP flag:標記此訊息為重複(duplicate)的訊息,只有在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE才會用到。
QoS level:設定此訊息的QoS level,只有在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE才會用到。
RETAIN:設定訊息是否要保留在server上,此特性只有PUBLISH才會用到。
Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,此欄位不一定就是1 byte,它是可變得,最多到4 byte。而且它會用特殊編碼來存放值,最高可以呈現到256MB,也就是說,你的Variable header + payload最大可以達到256MB。至於它編碼的部分可以去參考MQTT V3.1 Protocol Specification, Fixed header的介紹,會寫的比較詳細,這邊就不再多描述了。
看完上述的介紹之後會發現到,CONNECT Message的Fixed Header其實沒用到什麼特別的flag,只需要定對Message Type,然後根據編碼方式寫上正確的Remaining Length即可。
接著讓我們繼續往下看,再來是第二個Herader,也就是Variable Header。
Variable Header:
下面為一個CONNECT Message其Variable Header範例:
Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|---|
byte1 - byte8 | Protocol Name (MQIsdp) | ||||||||
byte9 | Version (3) | ||||||||
Connect Flags | |||||||||
byte 10 |
User name flag (1) Password flag (1) Will RETAIN (0) Will QoS (01) Will flag (1) Clean Session (1) |
1 | 1 | 0 | 0 | 1 | 1 | 1 | x |
byte 11 | Keep Alive MSB (0) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
byte 12 | Keep Alive LSB (10) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
主要分為三塊,分別為協定的資訊(byte1 ~ byte9)、此次連線的特性設定(byte 10)以及連線逾時時間設定。以下說明這些flag的用意:
Protocol name 和 Protocol version
協定的資訊包括協定的名稱和版本號碼,名稱為MQIsdp,版本號碼為3(0x03)。
Connect flags:
Connect flag原本有四個,分別為Clean session、Will、Will QoS和Retain flags,而MQTT3.1又新增了兩個Username和Password,底下就來一一介紹他們。
clean session flag
設定為0,代表是當client斷線時,server必須要把該位client訂閱哪個主題記錄下來。再該client斷線的期間,如果有QoS 1和QoS 2的訊息被發佈到該主題了,則server必須把訊息儲存下來,等到該client重新連線時能收到它沒收到的訊息。
設定為1,代表當client斷線時,server必須要清掉該位client所有的狀態,當client重新連線時,必須要再重新訂閱它感興趣的主題。
will flag、will QoS和will Retain flag
這三個flag,就是在MQTT簡介裡被提到的 最後遺囑(Last Will and Testament) 機制所用的flag。這機制是這樣的,client在一開始發送CONNECT訊息給server要求建立連線時,就把要對哪個主題說什麼遺言一起傳給server,當它在不正常的情況下斷線時(比如說網路連線斷掉、裝置故障等等),則這些訊息就會被server主動發佈到該主題上。如果是client主動發送DISCONNECT訊息給server要求斷線時,則此機制將不會有作用。
要啟動此機制,首先就是要將Will flag設為1,這樣就代表要啟用,之後你設定遺言的QoS level為何,server會依照你設定的QoS level來幫你傳送訊息,最後設定此此則遺言是否要保留(Retain)在server上。如果有設定Will flag,則在pyaload內會需要定義Will Topic和Will Message,也就是要對哪個主題發送什麼樣的遺言。
Username and Password flag
最後兩個flag為Useername和Password,意思是說此連線是否會包含帳號與密碼,如果有設定,則需要在payload內把帳號和密碼一起傳給server。要注意的是Password flag有設定而Username flag沒設定,此狀況是不被允許的。
Keep Alive timer
以秒為單位,指的是當server多久沒接收到從client發送過來的訊息時,就要認為與該client的網路連線已經斷掉了。此設定可以讓server不需要等待時間較長的TCP/IP timeout來得知網路狀況。Client有責任在此定義的時間內對server發過來的訊息作回應。如果在這時間內client和server都沒有訊息互傳的話,則client必須發送一個PINGREQ訊息給server,而server則回應一個PINGRESP message。
server會給client一個寬限時間,也就是會等1.5個Keep Alive timer時間,如果此段時間內client都沒送訊息過來,則server必須將此client斷線。
而client如果在Keep Alive time期間發送出PINGREQ訊息,卻一直沒收到PINGRESP訊息,則client必須關閉TCP/IP socket連線。
Keep Alive為2 byte,設定為0代表client不會斷線,通常只會設定幾分鐘。而此設定的最大值約為18小時。
Payload:
最後為CONNECT Message的payload,payload裡面包含什麼會跟你在variable header內的設定有關係,以下就來介紹payload裡面有些什麼。
Client Identifier
client唯一的識別碼,此識別碼在處理QoS level 1和2時會用到。長度限制為1~23個字,若超過23個字則會發生 Identifier Rejected的錯誤。
Will Topic and Will Message
如果在variable內有設定Will flag的話,代表此連線將要啟用最後遺囑(Last Will and Testament)機制,則payload就必須包含遺言內容和遺言要發送到哪個主題。
Username and Password
如果在variable內有設定Username flag和Password flag的話,代表此連線需要帳號與密碼,則payload就必須包含帳號和密碼。
小結
本篇介紹了MQTT的CONNECT Message,並介紹了一些MQTT的特性,讓程式開發人員在使用MQTT的相關library開發時,會知道建立連線可以設定的參數為何,其意義又為何。了解這些特性也會對應用MQTT的的架構規劃有所幫助。
沒有留言:
張貼留言