2014年3月16日 星期日

MQTT(三)CONNECT Message


前言:

前一篇提到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

bit76543210
byte 1Message Type(1)DUP flagQoS levelRETAIN
0001xxxx
byte 2Remaining 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範例:
Description76543210
byte1 - byte8Protocol Name (MQIsdp)
byte9Version (3)
Connect Flags
byte 10User name flag (1)
Password flag (1)
Will RETAIN (0)
Will QoS (01)
Will flag (1)
Clean Session (1)
1100111x
byte 11Keep Alive MSB (0)00000000
byte 12Keep Alive LSB (10)00001010
主要分為三塊,分別為協定的資訊(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的的架構規劃有所幫助。

參考:

沒有留言:

張貼留言