有空了和大家分享一下,如何從頭架構一個高效mqtt並行客戶端,基於傳統GPRS等較差網絡環境和網關等網絡環境好的情景(當然仔細講解mqtt的基本函數使很有必要的)。---這會正忙着搬磚
MQTt協議 第一個字節用來表示報表類型
接下來第二個字節開始是剩余長度
表示長度,最多用4個字節,變長,每個字節的高位表示后面是否還有表示長度的字節,也就是說每個字節可以表示128個字節的長度
本篇標注 標識符適用於qos大於0的情況。
其他細節
https://mcxiaoke.gitbooks.io/mqtt-cn/content/mqtt/02-ControlPacketFormat.html
本文要點
/** * Decodes the message length according to the MQTT algorithm * @param getcharfn pointer to function to read the next character from the data source * @param value the decoded length returned * @return the number of bytes read from the socket */ int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value) { unsigned char c; int multiplier = 1; int len = 0; #define MAX_NO_OF_REMAINING_LENGTH_BYTES 4 //讀取更多數據 FUNC_ENTRY; *value = 0; do { int rc = MQTTPACKET_READ_ERROR; if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) { rc = MQTTPACKET_READ_ERROR; /* bad data */ goto exit; } // rc = (*getcharfn)(&c, 1); // if (rc != 1) // goto exit; *value += (c & 127) * multiplier; multiplier *= 128; } while ((c & 128) != 0); exit: FUNC_EXIT_RC(len); return len; }
該代碼作用提取報文可變字節長度 ,最多提取4個字節
/** * Encodes the message length according to the MQTT algorithm * @param buf the buffer into which the encoded data is written * @param length the length to be encoded * @return the number of bytes written to buffer */ int MQTTPacket_encode(unsigned char* buf, int length) { int rc = 0; FUNC_ENTRY; do { char d = length % 128; length /= 128; /* if there are more digits to encode, set the top bit of this digit */ if (length > 0) d |= 0x80; buf[rc++] = d; } while (length > 0); FUNC_EXIT_RC(rc); return rc; }
該代碼作用,重新編碼長度信息到數組內,返回的就是長度的字節數
按照長度讀取字節數。將需要的字節讀取到目標數組,如果數組不夠就要重新處理
如果發現你的代碼有時候工作不正常,很可能你的mqtt源代碼是被人更改過得。
第一個buf是用戶提供給 該函數的一個空間,數據將按照mqtt格式化,buflen用戶告訴該函數 這個buff只有這么大。DUP重復分發標志,首次發送為0,重復發送為1,qos為0必須為0.
packedid 本次通訊包標識,對於qos為1和2的情況為了解決tcp傳輸產生的重復問題,使用該id區分不同的包,一次通訊 比如 訂閱 發送等,通訊過程只用一個相通的標識,占用的時候別人不可以使用該標識
通訊結束,釋放。該標示最大0xffff。
topicfilter 主題過濾通配符組,也就是可以多個主題一次性發送,相應的節省一定的流量,但是訂閱一般不是頻繁的使用,所以可以酌情使用。另一個就是qos組。