MQTT協議實現(一)
11年的時候,記錄寫過一篇文章《採用MQTT協議實現android消息推送》,那個時候,只是爲了實現推送的功能,沒有仔細閱讀過MQTT協議的內容。最近看同事又重新提起這個協議,於是就心血來潮去實現一下。MQTT協議是在tcp協議之上的,是基於TCP/IP的一個應用協議,正好可以驗證一下自己之前整理的基於tcp的RHSocket框架。
MQTT協議簡述
MQTT(Message Queue Telemetry Transport),遙測傳輸協議,提供訂閱/發佈模式,更爲簡約、輕量,易於使用,針對受限環境(帶寬低、網絡延遲高、網絡通信不穩定),對於移動互聯網的場景的消息推送十分有效。
特點如下:
1.使用發佈/訂閱消息模式,提供一對多的消息發佈,接觸應用程序耦合。
2.對負載內容屏蔽的消息傳輸。
3.使用TCP/IP提供網絡連接。
4.有三種消息發佈服務質量:“至多一次”,“至少一次”,“只有一次”
5.傳輸數據小(最小固定長度的頭部是2個字節),協議交換最小化,以降低網絡流量。
具體的協議內容可以從ibm網站學習:http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html
官方下載地址: http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/MQTT_V3.1_Protocol_Specific.pdf
也可以直接閱讀網友的博客:http://www.blogjava.net/yongboy/archive/2014/02/07/409587.html
閱讀了MQTT的協議內容後,會發現它其實和前面RHSocket框架中提到過的自定義協議內容類似,
協議頭(固定頭部fixedheader,可變頭部variableheader)+內容(內容載體payload)。
固定頭部(第一個固定協議字節,可變長度字節)
第一個字節(8位)
固定攜帶了4個數據內容,message type,dup flag,QoS level,retain。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
第0到3位,這4個bit是message type。
第4位,這1個bit是dup flag。
第5和6位,這2個bit是QoS level。
第7位,這1個bit是retain,預留位。
程序定義如下:
/** message type */
typedef NS_ENUM(UInt8, RHMQTTMessageType) {
RHMQTTMessageTypeConnect = 1, //client request to connect to server
RHMQTTMessageTypeConnAck = 2, //connect acknowledgment
RHMQTTMessageTypePublish = 3, //publish message
RHMQTTMessageTypePubAck = 4, //publish acknowledgment
RHMQTTMessageTypePubRec = 5, //publish received (assured delivery part 1)
RHMQTTMessageTypePubRel = 6, //publish release (assured delivery part 2)
RHMQTTMessageTypePubComp = 7, //publish complete (assured delivery part 3)
RHMQTTMessageTypeSubscribe = 8, //client subscribe request
RHMQTTMessageTypeSubAck = 9, //subscribe acknowledgment
RHMQTTMessageTypeUnsubscribe = 10, //client unsubscribe request
RHMQTTMessageTypeUnsubAck = 11, //unsubscribe acknowledgment
RHMQTTMessageTypePingReq = 12, //ping request
RHMQTTMessageTypePingResp = 13, //ping response
RHMQTTMessageTypeDisconnect = 14, //client is disconnecting
RHMQTTMessageTypeReserved = 15 //reserved
};
/** QoS(Quality of Service,服務質量) */
typedef NS_ENUM(UInt8, RHMQTTQosLevel) {
RHMQTTQosLevelAtMostOnce = 0, //至多一次,發完即丟棄,<=1
RHMQTTQosLevelAtLeastOnce = 1, //至少一次,需要確認回覆,>=1
RHMQTTQosLevelExactlyOnce = 2, //只有一次,需要確認回覆,=1
RHMQTTQosLevelReserved = 3 //待用,保留位置
};
可變長度字節(爲可變頭部和協議內容的長度之和,動態計算獲得,最小爲1個字節0x7F,最大爲4個字節0xFF,0xFF,0xFF,0x7F)
0xff | 0xff | 0xff | 0x7f |
至於爲什麼不是0xff,http://www.blogjava.net/yongboy/archive/2014/02/07/409587.html中有說明,是MQTT協議規定所致。
可變頭部
可變頭部,協議中不同的命令,攜帶的數據內容也不同。http://www.blogjava.net/yongboy/archive/2014/02/09/409630.html後續通過程序實現分別說明。
包體內容
同上。
具體的內容,已經提供了學習連接,我就不拷貝了,哈哈。
閱讀相關的內容後,應該大概瞭解MQTT協議的字段定義了,下一篇我們從MQTT協議的連接入手,來一步步的學習。
相關代碼已經提交到github,https://github.com/zhu410289616/RHMQTTKit