MQTT是輕量級基於代理的發佈/訂閱的消息傳輸協議,它能夠經過不多的代碼和帶寬和遠程設備鏈接。例如經過衛星和代理鏈接,經過撥號和醫療保健提供者鏈接,以及在一些自動化或小型設備上,並且因爲小巧,省電,協議開銷小和能高效的向一和多個接收者傳遞信息,故一樣適用於稱動應用設備上。php
相信在想深刻學習這協議必是奔着解決某個問題而來的,上面給出了適用的場景,我之因此想深刻的學習和了解這個協議,理由以下:linux
一、能夠實現手機消息推送(PUSH)服務器
二、協議簡單,最小的頭部只需2個字節,特別適合於嵌入式中。session
三、這是個瞭解什麼是協議絕好的例子。相比於其它複雜的協議例如tcp,http協議,至少說明文檔看的下去。socket
在這裏,我以推送爲例子說明,雖然如今現成的推送解決方案已經比較成熟,可是這個Repeat ReInvent the Whell仍是要作一下,什麼都是拿來主義,和搬運工有什麼區別。tcp
先說一下整個協議的構造,總體上協議可拆分爲:ide
固定頭部+可變頭部+消息體學習
協議說白了就是對於雙方通訊的一個約定,好比傳過來一段字符流,第1個字節表示什麼,第2個字節表示什麼。。。。一個約定。ui
因此在固定頭部的構造以下:編碼
public $operations=array( "MQTT_CONNECT"=>1,//請求鏈接 "MQTT_CONNACK"=>2,//請求應答 "MQTT_PUBLISH"=>3,//發佈消息 "MQTT_PUBACK"=>4,//發佈應答 "MQTT_PUBREC"=>5,//發佈已接收,保證傳遞1 "MQTT_PUBREL"=>6,//發佈釋放,保證傳遞2 "MQTT_PUBCOMP"=>7,//發佈完成,保證傳遞3 "MQTT_SUBSCRIBE"=>8,//訂閱請求 "MQTT_SUBACK"=>9,//訂閱應答 "MQTT_UNSUBSCRIBE"=>10,//取消訂閱 "MQTT_UNSUBACK"=>11,//取消訂閱應答 "MQTT_PINGREQ"=>12,//ping請求 "MQTT_PINGRESP"=>13,//ping響應 "MQTT_DISCONNECT"=>14//斷開鏈接 );
其是用來在保證消息傳輸可靠的,若是設置爲1,則在下面的變長頭部裏多加MessageId,並須要回覆確認,保證消息傳輸完成,但不能用於檢測消息重複發送。
主要用於PUBLISH(發佈態)的消息,表示服務器要保留此次推送的信息,若是有新的訂閱者出現,就把這消息推送給它。若是不設那麼推送至當前訂閱的就釋放了。
是用來保存接下去的變長頭部+消息體的總大小的。
可是不是並非直接保存的,一樣也是能夠擴展的,其機制是,前7位用於保存長度,後一部用作標識。
我舉個例了,即若是計算出後面的大小爲0<length<=127的,正常保存
若是是127<length<16383的,則須要二個字節保存了,將第一個字節的最大的一位置1,表示未完。而後第二個字節繼續存。
拿130來講,第一個字節存10000011,第二個字節存000000001,也就是0x83,0x01,把兩個字節連起來看,第二個字節權重從2的8次開始。
同起能夠加第3個字節,最多能夠加至第4個字節。故MQTT協議最多能夠實現268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)將近256M的數據。可謂能伸能縮。
可變頭部
這個是可變頭部的全貌。
一、首先最上面的8個字節是Protocol Name(編碼名),UTF編碼的字符「MQIsdp」,頭兩個是編碼名提長爲6。
這裏多說一些,接下去的協議多采用這種方式組合,即頭兩個字節表示下一部分的長,而後後面跟上內容。這裏頭兩個字節長爲6,下面跟6個字符「MQIsdp」。
二、Protocol Version,協議版本號,v3 也是固定的。
三、Connect Flag,鏈接標識,有點像固定頭部的。8位分別表明不一樣的標誌。第1個字節保留。
Clean Session,Will flag,Will Qos, Will Retain都是相對於CONNECT消息來講的。
Clean Session:0表示若是訂閱的客戶機斷線了,那麼要保存其要推送的消息,若是其從新鏈接時,則將這些消息推送。
1表示消除,表示客戶機是第一次鏈接,消息因此之前的鏈接信息。
Will Flag,表示若是客戶機在不是在發送DISCONNECT消息中斷,好比IO錯誤等,將些置爲1,要求重傳。而且下且的WillQos和WillRetain也要設置,消息體中的Topic和MessageID也要設置,就是表示發生了錯誤,要重傳。
Will Qos,在CONNECT非正常狀況下設置,通常若是標識了WillFlag,那麼這個位置也要標識。
Will RETAIN:一樣在CONNECT中,若是標識了WillFlag,那麼些位也必定要標識
usename flag和passwordflag,用來標識是否在消息體中傳遞用戶和密碼,只有標識了,消息體中的用戶名和密碼才用效,只標記密碼而不標記用戶名是不合法的。
四、Keep Alive,表示響應時間,若是這個時間內,鏈接或發送操做未完成,則斷開tcp鏈接,表示離線。
五、Connect Return Code即一般於CONNACK消息中,表示返回的鏈接狀況,我能夠經過此檢驗鏈接狀況。
六、Topic Name,訂閱消息標識,MQTT是基於訂閱/發佈的消息,那麼這個就是消息訂閱的標識,像新聞客戶端裏的訂閱不一樣的欄目同樣。用於區別消息的推送類別。
主要用於PUBLISH和SUBSCRIBE中。最大可支持32767個字符,即4個字節。
消息體(PayLoad)
只有3種消息有消息體CONNECT,SUBSCRIBE,SUBACK
CONNECT主要是客戶機的ClientID,訂閱的Topic和Message以及用戶名和密碼,其於變長頭部中的will是對應的。
SUBSCRIBE是包含了一系列的要訂閱的主題以及QOS。
SUBACK是用服務器對於SUBSCRIBE所申請的主題及QOS進行確認和回覆。
而PUBLISH是消息體中則保存推送的消息,以二進制形式,固然這裏的編輯可自定義。
七、Message Identifier
包含於PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK.
其爲16位字符表示,用於在Qos爲1或2時標識Message的,保證Message傳輸的可靠性。
至於具體的消息例子,咱們在後面的代碼中慢慢體現。
一、PHP+Apache或Nginx
二、安裝開源代理程序Mosquitto,這裏用其作爲代理服務器,負責鏈接和分發。
安裝方法很簡單,http://mosquitto.org/files/ binary是編譯好的,source是源碼安裝須要的(make & make install 就行)
惟 一要配置的就是在解壓後的config.mk,安裝完後設置文件是mosquitto.conf
固然主要是設置是否支持ssl,還有就是config.mk最下面的安裝位置的設定。這裏一切默認。
默認啓動是綁定的IP是本地IP,端口是1883能夠在mosquitto.conf裏設置(要去掉前面的#字註釋),linux 中 -c 能夠指定設置文件並運行
比 如: mosquitto -c /etc/mosquitto.conf