2014年3月16日 星期日

MQTT(七)DISCONNECT Message And Review

前言:

前篇介紹了UNSUBSCRIBE Message,此訊息個人是覺得會當某個使用者從整合了MQTT系統的服務登出時,需要對MQTT Broker取消註冊,本想說上一篇是這系列的最後一篇文章,在撰寫時卻突然想到,服務登出除了取消訂閱之外,還有個斷線訊息要送吧!因此又多了此篇,來介紹Client要對Server斷開連線所發送的訊息,DISCONNECT Message。

DISCONNECT Message

DISCONNECT Message為client發送給server,表示client將要斷掉它的TCP/IP連線。比起直接將連線斷掉的方式來斷線,使用此訊息來斷線會是種比較乾淨的做法。
如果Client當初在連線時有設置clean session flag,則該位client之前在MQTT Broker上面的資訊將會被清除掉。Server在關閉TCP/IP連線時,不會給client任何回應。

Fixed Header:

bit76543210
byte 1Message Type(14)DUP flagQoS levelRETAIN
1110xxxx
byte 2Remaining Length
00000000
上面為DISCONNECT Message裡面的fixed header,Message Type爲14,因此爲1110。其他DUP flag、QoS level以及RETAIN皆沒有使用到。
而DISCONNECT Message也沒有Variable header和Payload,因此其Remaining Length爲00000000。
DISCONNECT Message和上篇介紹的PINGREQ Message一樣,只有2 byte而已,也是非常輕量化的訊息。

Review:

最後依照架構MQTT服務與程式設計的觀點,將幾個訊息以及其需要注意的參數設定與特性,用圖片列出來。

CONNECT Message


在Client要對MQTT Broker建立連線時會用到的訊息,其中裡面需要設定:
  • Clean Session Flag:當Cleint斷線時,Broker該怎麼處理,是要幫他保留訊息,還是不管,等Client自己重新連線後在過來重新訂閱感興趣的主題。
  • Will:設定是否要使用MQTT的遺言功能(Last Will and Testament),要使用的話,則要將相關欄位與資料一併傳給Broker。
  • Username & Password:Broker會決定建立連線時需不需要帳號密碼,如果需要則Client要把帳號密碼放在CONNECT Message一併送給Broker。
  • Keep Aliver timer:代表此連線的過期時間,以秒為單位。也就是說如果Client和Broker在這段期間內雙方都沒有對發送任何訊息,則Broker要將該Client視為斷線。
  • Client Identifier:Client獨一無二的識別碼,可以帶該位使用者在這系統內所使用的帳號。
更多CONNECT Message的細節可以參考先前的文章MQTT(三)CONNECT Message

PUBLISH Message


在Client要對Broker上的某個主題發佈訊息時會用到,其中裡面需要設定欄位與資料的有:
  • Qos level:此訊息傳送時所要用的QoS level為何,可以是0(只傳一次)、1(至少傳一次)或2(確定對方會收到一次)。
  • RETAIN:Broker上面的主題,是否要保留此訊息,當成是該主題上最新的一筆訊息。設定為RETAIN,則Broker會將此訊息保留起來,直到下一個RETAIN訊息發佈過來為止。當有新的Client對此主題訂閱,則Broker會把此主題上最新的RETAIN訊息傳給它。
  • Topic name:此次發佈訊息的主題,要注意的是這邊不能用萬用字元,主題名稱必須是完整的。
  • Payload:要發佈的訊息內容。
更多PUBLISH Message的細節可以參考先前的文章MQTT(四)PUBLISH Message

SUBSCRIBE Message


在Client對Broker上的某個主題感興趣時,可以透過SUBSCRIBE Message來訂閱該主題,其中裡面需要設定欄位很單純,只有Topic name & Requested QoS level,也就是想要訂閱的主題,以及訂閱主題時期望的QoS level為何。
這邊可以一次傳送多個Topic name,透過SUBSCRIBE Message同時訂閱多個主題。或者是說利用萬用字元(#或+)的方式來一定訂閱多個主題。
關於SUBSCRIBE Message的細節可以參考先前的文章MQTT(五)SUBSCRIBE Message

UNSUBSCRIBE Message


最後要談到的就是UNSUBSCRIBE Message,UNSUBSCRIBE Message也是跟SUBSCRIBE Message一樣,可以透過在一個Message裡面傳多個Topic的方式來一次取消訂閱多個主題。
另外有一點需要特別提出來,就是MQTT3.1版在規格裡面並沒有說到UNSUBSCRIBE Message可以使用萬用字元!但是在上面的圖為何要把他標出來呢,是因為我到網路上搜尋了相關資訊,發現到了這串位於MQTT官方的Google網上論壇這串討論串Topic Wildcards,提問者對此發表疑問,並且有人回答萬用字元是可以用在UNSUBSCRIBE Message的。
更多UNSUBSCRIBE Message的細節可以參考先前的文章MQTT(六)UNSUBSCRIBE Message And PINGREQ Message

小結

本篇介紹了MQTT的DISCONNECT Message,在Client想斷開連線時,必須傳送此訊息給Server,讓Server可以清理不必要的資料,節省資源。
本篇也以系統架構和程式開發的觀點,將MQTT幾個重要的訊息和其參數列出來,以方便讓人理解在使用上需要注意些什麼。
以上MQTT的介紹系列,將會告一個段落,接下來會從實作面的部分來繼續延伸MQTT此主題。

參考:

MQTT(六)UNSUBSCRIBE Message And PINGREQ Message

前言:

上一篇提到用來訂閱主題的SUBSCRIBE Message,接著最後要介紹的兩個訊息,分別為取消訂閱用的UNSUBSCRIBE Message以及用來與Server維持連線的PINGREQ Message。

UNSUBSCRIBE Message

UNSUBSCRIBE Message為client發送給server,用來取消訂閱主題。

Fixed Header:

bit76543210
byte 1Message Type(10)DUP flagQoS levelRETAIN
1010001x
byte 2Remaining Length
上面為UNSUBSCRIBE Message裡面的fixed header,以下依依介紹它們的作用。
  • Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是SUBSCRIBE Message的關係,因此會填上1010。
  • DUP flag:標記此訊息為重複(duplicate)的訊息,會用在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE上。當client或是server要重新傳送上述訊息時,則要將此flag設為1。此flag會適用於QoS大於0的訊息。
    此flag 只能當成一種提示,表示此則訊息可能在之前有收過了,不應該拿它來當成訊息重複的檢查flag。
  • QoS level:UNSUBSCRIBE Message使用QoS level 1來回應(acknowledge)不同的取消訂閱主題請求。
  • RETAIN:沒有使用到。
  • Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,此欄位不一定就是1 byte,它是可變得,最多到4 byte。
接著讓我們繼續往下看,再來是第二個Herader,也就是Variable Header。

Variable Header:

由於UNSUBSCRIBE Message QoS level為1,因此其variable header會包含Message ID,用來確保訊息能夠正確傳送。
下面為SUBSCRIBE Message,variable header欄位範例:
FieldValue
Message ID10

Payload:

UNSUBSCRIBE Message的payload會包含一個主題名稱列表,代表該Client想要取消訂閱的主題。下表爲其payload範例,代表該Client想要取消訂閱兩個主題"a/b"、"c/d":
Topic name"a/b"
Topic name"c/d"

Response:

取消註冊成功,Server會回應一個UNSUBACK Message給client。

看完UNSUBACK Message的介紹之後,緊接著要介紹PINGREQ Message。

PINGREQ Message

PINGREQ Message為client發送給server,用來詢問Server是否還活著。Server收到來自Client的PINGREQ Message之後,會將該位Client的Keep Alive timer歸零重新計算,否則當Keep Alive timer時間到了,則Server會視此Client爲斷線狀態,Server將會關閉TCP socket連線(詳情可參考MQTT(三)CONNECT Message#Keep Alive timer)。因此這訊息反過來說,也算是Client用來回報自己狀況的給Server的訊息。

Fixed Header:

bit76543210
byte 1Message Type(12)DUP flagQoS levelRETAIN
1100xxxx
byte 2Remaining Length
00000000
上面為PINGREQ Message裡面的fixed header,以下依依介紹它們的作用。
  • Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是PINGREQ Message的關係,因此會填上1100。
  • DUP flag:標記此訊息為重複(duplicate)的訊息,PINGREQ Message不會用到此欄位。
  • QoS level:定義該則訊息的QoS level為何,PINGREQ Message不會用到此欄位。
  • RETAIN:沒有使用到。
  • Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,PINGREQ Message沒有Variable header,也沒有Payload,因此該欄位爲00000000。
由上面的Fixed header可得知,在MQTT的規範裡,PINGREQ Message是非常輕量化的,只有2 byte而已,因此PINGREQ Message非常適合用來作為機器間互相了解彼此間狀態的訊息。

Response:

Server收到PINGREQ Message,會回應一個PINGRES Message給client,告訴Client它還活著,PINGRES Message跟PINGREQ一樣,也是2 byte而已。

小結

本篇介紹了MQTT的UNSUBSCRIBE Message和PINGREQ Message。
UNSUBSCRIBE此訊息用於取消訂閱主題上,它需要注意的地方在於它可以一次同時取消多個主題。而另外介紹的PINGREQ訊息,此訊息可以讓Client運用最小的頻寬耗損,去告知Server它的狀態,Server也可以反過來利用此訊息得知Client的狀況,避免彼此間裝置上的資源造成不必要的消耗。

參考:

MQTT(五)SUBSCRIBE Message

前言:

上一篇提到用來發佈訊息的PUBLISH Message,接著就來談談訂閱訊息用的SUBSCRIBE Message。

SUBSCRIBE Message

SUBSCRIBE Message允許client對Server上一或多個感興趣的主題(Topic)進行訂閱。當有訊息對主題發佈時,server會將訊息當作PUBLISH Message送給訂閱的client。SUBSCRIBE Message也定義了QoS level,表示它期望以何種QoS level來接收訊息。

Fixed Header:

bit76543210
byte 1Message Type(8)DUP flagQoS levelRETAIN
1000001x
byte 2Remaining Length
上面為SUBSCRIBE Message裡面的fixed header,以下依依介紹它們的作用。
  • Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是SUBSCRIBE Message的關係,因此會填上1000。
  • DUP flag:標記此訊息為重複(duplicate)的訊息,會用在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE上。當client或是server要重新傳送上述訊息時,則要將此flag設為1。此flag會適用於QoS大於0的訊息。
    此flag 只能當成一種提示,表示此則訊息可能在之前有收過了,不應該拿它來當成訊息重複的檢查flag。
  • QoS level:SUBSCRIBE Message使用QoS level 1來回應(acknowledge)不同的訂閱主題請求。
  • RETAIN:沒有使用到。
  • Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,此欄位不一定就是1 byte,它是可變得,最多到4 byte。
接著讓我們繼續往下看,再來是第二個Herader,也就是Variable Header。

Variable Header:

由於SUBSCRIBE Message QoS level為1,因此其variable header會包含Message ID,用來確保訊息能夠正確傳送。
下面為SUBSCRIBE Message,variable header欄位範例:
FieldValue
Message ID10

Payload:

SUBSCRIBE Message的payload會包含一個主題名稱列表,代表該Client想要訂閱的主題,列表內的每個主題都會包括一個期望接收訊息時的QoS level,可以參考MQTT(二)Message Type and Flows:Subscribe Flow來了解QoS level與其影響為何。
主題的名稱可以使用萬用字元(wildcard characters),關於萬用字元稍後會進行說明,以下為SUBSCRIBE Message的payload範例:
Topic name"a/b"
Requested QoS1
Topic name"c/d"
Requested QoS2
上述範例代表該Client想要訂閱兩個主題"a/b"、"c/d",其中主題"a/b"期望用QoS level 1來接收訊息,主題"c/d"期望用QoS level 2來接收訊息。

Response:

當Server接收到從Cleint發送過來的SUBSCRIBE Message,則回應一個SUBACK Message給client。
Server有基於Client已經訂閱的關係,因此可能會開始傳送PUBLISH Message給Client,即使Client還沒收到SUBACK Message。
Server有可能會降低cleint請求的QoS level。這會發生在Server沒辦法提供高level的QoS時。舉例來說,如果Server沒有提供一個可靠的訊息持久機制(persistence mechanism),則它可能只提供QoS level 0給訂閱者。Server提供的QoS level會在SUBACK Message的payload內,依照主題的訂閱順序回應給訂閱者。以下為範例:
Granted QoS0
Granted QoS2

主題萬用字元(Topic WildCard Characters):

在訂閱的時候可以使用特出字元,允許你一次訂閱多個主題,此字元稱為萬用字元。
主題層級分隔符號(Topic level separator)被用來對主題做結構化。單一層級的萬用字元和多層級的萬用字元可以被用在訂閱上面,但是不能被用在發佈(publish)訊息上面,也就是說在發佈訊息時,主題要明確定義,不能用萬用字元來同時對多個主題做訊息發佈。

Topic level separator(主題層級分隔符號):

斜線符號(/)用來切割topic tree的每個層級,提供一個有層次的主題空間。使用主題層級分割符號來切割主題,在遇到用萬用字元訂閱該主題時是很有用的,下面接著介紹兩個萬用字元。

Multi-level wildcard(多層級萬用字元):

井字號(#)用來匹配任何層級的主題。舉例來說,如果你用此萬用字元訂閱了 finance/stock/ibm/#,則你將會收到來自於下列主題的訊息:
  • finance/stock/ibm
  • finance/stock/ibm/closingprice
  • finance/stock/ibm/currentprice
多層級萬用字元可以表示零到多個層級,因此 finance/# 可以匹配到finance 。
多層級萬用字元在以下狀況是有效的,如 # 或是 finance/# ,而以下狀況下是無效的,如 finance# 和 finance/#/closingprice 。

Single-level wildcard(單一層級萬用字元):

加字號(+)用來匹配單一層級的主題。舉例來說 finance/stock/+ 會匹配 /finance/stock/ibm 和 /finance/stock/xyz ,但是不會匹配到finance/stock/ibm/closingprice 。也由於它只會匹配到一個層級,因此 finance/+ 不會匹配到 finance 。
單一層級萬用字元可以使用在任何層級的主題樹,也可以和多層級萬用字元結合使用。
單一層級萬用字元在以下狀況是有效的,如 + 和 finance/+ 以及finance/+/ibm 。而以下狀況是無效的,如 finance+ 。

小結

本篇介紹了MQTT的SUBSCRIBE Message,此訊息用於訂閱主題上,而每個想訂閱的主題需要設定期望的QoS level,藉此來表達client對該主題的訊息品質需求。
另外也介紹了主題萬用字元,讓client在訂閱主題時,可以透過萬用字元同時對多個主題進行訂閱。

參考:

MQTT(四)PUBLISH Message

前言:

上一篇提到建立起連線用的CONNECT Message,接著來談談和發佈訊息有關的Message,PUBLISH Message。

PUBLISH Message

PUBLISH Message是發佈訊息時會用到的訊息類型,它會使用在兩個方向:
  1. client對某個主題(Topic)散佈訊息,此時它會發送PUBLISH Message給Server。
  2. server收到了client發送給某個主題的訊息,server會把這些訊息已PUBLISH Message的方式發送給訂閱此主題的client。
每個PUBLISH Message都會包含一個topic name,代表此訊息要發送給哪個主題。

Fixed Header:

bit76543210
byte 1Message Type(1)DUP flagQoS levelRETAIN
00110010
byte 2Remaining Length
上面為PUBLISH Message裡面的fixed header,以下依依介紹它們的作用。
  • Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是PUBLISH Message的關係,因此會填上0011。
  • DUP flag:標記此訊息為重複(duplicate)的訊息,會用在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE上。當client或是server要重新傳送上述訊息時,則要將此flag設為1。此flag會適用於QoS大於0的訊息。
    此flag 只能當成一種提示,表示此則訊息可能在之前有收過了,不應該拿它來當成訊息重複的檢查flag。
  • QoS level:設定此訊息的QoS level,只有在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE才會用到。可以參考MQTT(二)Message Type and Flows:PUBLISH flow來得知比較詳細的資訊。
  • RETAIN:設定訊息是否要保留在server上,此特性只有PUBLISH才會用到。當client發送PUBLISH Message給Server上的某個Topic時,如果將此flag設為1,則Server將此訊息發佈給當前的所以訂閱者後,必須將此訊息保留。
    當有一個新的client對此Topic進行訂閱,則Server必須把最後一則Retain flag設為1的訊息傳送給該client。被設為Retain的訊息必須保留直到Server重啟為止。
    此機制會適用於訊息與訊息之間會有一段時間的場景,也就是說,訊息的發佈(Publish)可能不是那麼的頻繁,如錯誤回報的系統。它可以讓新的訂閱者馬上知道上次的最新狀況為何。
  • Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,此欄位不一定就是1 byte,它是可變得,最多到4 byte。
接著讓我們繼續往下看,再來是第二個Herader,也就是Variable Header。

Variable Header:

PUBLISH Message的Variable header會包含以下欄位:
  • Topic name:
    一個UTF的編碼字串,它必須是一個明確的主題定義。不能為萬用字元(wildcard characters),關於萬用字元會在後面的篇幅做介紹。這邊只需知道,當訂閱者用萬用字元訂閱到此主題時,此訂閱者收到的PUBLISH訊息裡面的Topic name欄位會是完整的名稱,而不是用萬用字元匹配到的名稱。
  • Message ID:
    Message ID會使用在QoS level 1或是2的下列訊息上面:PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK。
    Message ID為16bit無符號的整數,代表特定方向訊息唯一的id,每個client都會維護他們自己的Message ID列表。所以有可能會有一種狀況發生,就是某個client在發佈Message ID為1的訊息給server時,同時收到Server發佈過來Message ID為1的訊息。
    Message ID不能為0,它會被視為無效的Message ID。
    下面為PUBLISH Message QoS level為1時,variable header欄位範例:
FieldValue
Topic Name:"a/b"
Message ID10

Payload:

PUBLISH Message的payload會包含要發佈的訊息內容。Payload長度為0的訊息是有效的。

Response:

PUBLISH Message的回應會跟QoS level有關係,下表顯示QoS level與預期的回應:
Qos LevelExpected response
Qos 0None
QoS 1PUBACK
QoS 2PUBREC
PUBLISH Message可以是從client發佈給Server,或者是從server發佈給訂閱者。在收到訊息時,根據QoS level會做以下的動作:
  • QoS 0:
    將訊息提供給任何有興趣的訂閱者。
  • QoS 1:
    將訊息記錄到儲存裝置(persistent storage),將它提供給任何有興趣的訂閱者,然後回傳PUBACK給發送端。
  • QoS 2:
    將訊息記錄到儲存裝置,不要馬上將它提供給任何有興趣的訂閱者,先回傳PUBREC給發送端。
可以參考MQTT(二)Message Type and Flows:PUBLISH flow來得知比較詳細的資訊。

小結

本篇介紹了MQTT的PUBLISH Message,PUBLISH Message其實要注意的就是QoS level和Retain這兩個特性,QoS level會影響到訊息的可靠度,而Retain可以讓新的訂閱者在訂閱主題時就能得知此主題最新的狀態。了解這兩個特性會可以幫助整體服務架構的規劃。
另外還需要注意到,一次只能對一個Topic發佈訊息,所以沒辦法做到一次同時對多個Topic發不訊息。

參考:

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的的架構規劃有所幫助。

參考: