記事のディレクトリ
関連記事
1.「MQTTプロトコル分析の概要(1)」
2.「MQTTプロトコル分析の概要(2)」
3。「[IoT] BaiduIoTクラウドへの接続方法」
4。「[FreeRTOS] LWIP2.1のSTM32移植に基づくMQTT .2》
1はじめに
MQTT 3(現在のバージョン3.1.1
)は現在最も広く使用されていますMQTTプロトコル標準。がMQTT 5規格がリリースされている、といくつかのエキサイティングな新機能をもたらしていますが、アプリケーション全体のシナリオでは、業界の変遷のバージョンから3への5はしばらく続くことがあります。MQTTの最大の利点は、コードが非常に少なく、帯域幅が限られているリモートデバイスにリアルタイムで信頼性の高いメッセージングサービスを提供できることです。MQTTは、低オーバーヘッド、低帯域幅のインスタントメッセージングプロトコルとして、モノのインターネット、小型デバイス、およびモバイルアプリケーションに幅広いアプリケーションを備えています。
2.MQTTプロトコルの実装方法
MQTTプロトコルを実現するには、クライアントとサーバー間の通信を完了する必要があります。通信プロセスでは、MQTTプロトコルにはパブリッシャー(発行)、エージェント(ブローカーサーバー)、サブスクライバー(サブスクライブ)の3つのIDがあります。その中で、メッセージの発行者とサブスクライバーは両方ともクライアントであり、メッセージブローカーはサーバーであり、メッセージ発行者は同時にサブスクライバーになることができます。
MQTTによって送信されるメッセージは、トピックとペイロードの2つの部分に分けられます。
- (1)
Topic
、メッセージのタイプとして理解でき、サブスクライバー订阅(Subscribe)
はトピックを受け取ります消息内容(payload)
; - (2)
payload
メッセージの内容として理解できます。これは、サブスクライバーが使用したい特定のコンテンツを指します。
3.MQTT制御メッセージ形式
MQTTプロトコルTCPで作業している場合、エンドとエージェントは事前定義された制御メッセージを交換して通信を完了します。MQTTメッセージは、次の順序で表示される3つの部分で構成されています。
固定ヘッダー | 固定ヘッダー、すべての制御メッセージには次のものが含まれます |
---|---|
可変ヘッダー | 可変ヘッダー、制御メッセージの一部に含まれる |
ペイロード | ペイロード、制御メッセージの一部に含まれています |
3.1固定ヘッダーのフォーマット
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
バイト1 | MQTT制御パケットの種類 | 制御メッセージのタイプを指定するために使用されるフラグビット | ||||||
バイト2..。 | 残りの長さ |
- MQTT制御パケットの種類
ファーストネーム | 値 | メッセージの流れの方向 | 説明 |
---|---|---|---|
予約済み | 0 | 禁止する | 保つ |
接続する | 1 | クライアントからサーバーへ | クライアントがサーバーへの接続を要求する |
コナック | 2 | サーバーからクライアントへ | 接続メッセージの確認 |
公開 | 3 | 両方向が許可されます | ニュースリリース |
PUBACK | 4 | 両方向が許可されます | QoS1メッセージリリースの確認 |
PUBREC | 5 | 両方向が許可されます | リリースして受け取る(確実に配信するための最初のステップ) |
PUBREL | 6 | 両方向が許可されます | リリースとリリース(保証付き配信の2番目のステップ) |
PUBCOMP | 7 | 両方向が許可されます | QoS 2ニュースリリースが完了しました(対話の3番目のステップが保証されています) |
申し込む | 8 | クライアントからサーバーへ | クライアントサブスクリプションリクエスト |
SUBACK | 9 | サーバーからクライアントへ | サブスクリプションリクエストメッセージの確認 |
購読解除 | 10 | クライアントからサーバーへ | クライアントの退会リクエスト |
UNSUBACK | 11 | サーバーからクライアントへ | 購読解除メッセージの確認 |
PINGREQ | 12 | クライアントからサーバーへ | ハートビートリクエスト |
PINGRESP | 13 | サーバーからクライアントへ | ハートビート応答 |
切断 | 14 | クライアントからサーバーへ | クライアントが切断されました |
予約済み | 15 | 禁止する | 保つ |
-
残りの長さの
位置: 2番目のバイトから始まります。残りの長さ(残りの長さ)は、変数ヘッダーとペイロードデータを含む、現在のメッセージの残りの部分のバイト数を表します。残りの長さには、残りの長さフィールド自体をエンコードするために使用されるバイト数は含まれません。
残りの長さフィールドに1つ使用します可変長コーディングスキーム、128未満の値にはシングルバイトエンコーディングを使用します。大きい値は次のように処理されます。下位7ビットはデータのエンコードに使用され、最上位ビットはさらにバイトがあるかどうかを示すために使用されます。したがって、各バイトは128個の値と継続ビットをエンコードできます。残りの長さフィールドの最大数は4バイトです。
バイト数 | 最小 | マックス |
---|---|---|
1 | 0(0x00) | 127(0x7F) |
2 | 128(0x80、0x01) | 16 383(0xFF、0x7F) |
3 | 16 384(0x80、0x80、0x01) | 2 097 151(0xFF、0xFF、0x7F) |
4 | 2 097 152(0x80、0x80、0x80、0x01) | 268 435 455(0xFF、0xFF、0xFF、0x7F) |
それぞれ(各バイトの下位7ビットはデータのエンコードに使用され、最上位ビットはフラグビットです):
- 1バイトの場合、0(0x00)から127(0x7f)
- 2バイトの場合、128(0x80、0x01)から16383(0Xff、0x7f)
- 3バイトで、16384(0x80、0x80、0x01)から2097151(0xFF、0xFF、0x7F)
- 4バイトの場合、2097152(0x80、0x80、0x80、0x01)から268435455(0xFF、0xFF、0xFF、0x7F)
可変長コーディング方式 を使用した非負の整数Xのアルゴリズムは次のとおりです。
do
encodedByte = X MOD 128
X = X DIV 128
// if there are more data to encode, set the top bit of this byte
if ( X > 0 )
encodedByte = encodedByte OR 128
endif
'output' encodedByte
while ( X > 0 )
MODはモジュロ演算、DIVは整数除算、ORはビット演算、または(%、/、| C言語)
対応するC言語コードは次のとおりです。
/**
* 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;
}
残りの長さフィールドの 可変長デコード方式 アルゴリズムは次のとおりです。
multiplier = 1
value = 0
do
encodedByte = 'next byte from stream'
value += (encodedByte AND 127) * multiplier
if (multiplier > 128*128*128)
throw Error(Malformed Remaining Length)
multiplier *= 128
while ((encodedByte AND 128) != 0)
ANDはビット演算であり、(C言語では&)
このアルゴリズムが終了すると、valueには残りの長さの値が含まれます。
対応するC言語コードは次のとおりです。
/**
* 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;
}
3.2変数ヘッダー
いくつかMQTT制御メッセージ可変ヘッダー部分が含まれています。固定ヘッダーとペイロードの間にあります。変数ヘッダーの内容は、メッセージの種類によって異なります。変数ヘッダーのメッセージ識別子(Packet Identifier
)フィールドは、複数のタイプのメッセージに存在します。
注:変数ヘッダーはメッセージIDを参照するだけでなく、以下は例としてのみ使用されます。MQTTメッセージタイプが異なれば、変数ヘッダーも異なります。
メッセージ識別子バイトは次のとおりです。
ビット | 7 - 0 |
---|---|
バイト1 | メッセージ識別子MSB |
バイト2 | メッセージ識別子LSB |
多くの制御メッセージの可変ヘッダー部分には、2バイトのメッセージ識別子フィールドが含まれています。メッセージIDを必要とする制御メッセージを次の表に示します。
制御メッセージ | メッセージ識別子フィールド |
---|---|
接続する | 必要ありません |
コナック | 必要ありません |
公開 | 必須(QoS> 0の場合) |
PUBACK | 必要 |
PUBREC | 必要 |
PUBREL | 必要 |
PUBCOMP | 必要 |
申し込む | 必要 |
SUBACK | 必要 |
購読解除 | 必要 |
UNSUBACK | 必要 |
PINGREQ | 必要ありません |
PINGRESP | 必要ありません |
切断 | 必要ありません |
クライアントとサーバーは、互いに独立してメッセージ識別子を割り当てます。したがって、同じメッセージ識別子を使用するクライアントとサーバーの組み合わせにより、同時メッセージ交換を実現できます。例は次のとおりです。
3.3ペイロード
特定のMQTT制御パケットメッセージの最後の部分に含まれるペイロードのために、PUBLISH
それがアプリケーション・メッセージ・ペイロードです。
ペイロードを含む制御パケット
制御メッセージ | ペイロード |
---|---|
接続する | 必要 |
コナック | 必要ありません |
公開 | オプション |
PUBACK | 必要ありません |
PUBREC | 必要ありません |
PUBREL | 必要ありません |
PUBCOMP | 必要ありません |
申し込む | 必要 |
SUBACK | 必要 |
購読解除 | 必要 |
UNSUBACK | 必要ありません |
PINGREQ | 必要ありません |
PINGRESP | 必要ありません |
切断 | 必要ありません |
4.MQTT制御メッセージ
特定の各メッセージは、次の記事で紹介されています:「MQTTプロトコル分析の概要(2)」
5.参考資料
MQTT 5.0プロトコルの中国語バージョン:
https://github.com/twoFiveOneTen/MQTT_V5
MQTTバージョン5.0:
http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0- cs02 .htm
MQTT 3.1.1プロトコル中国語バージョン:
https://github.com/mcxiaoke/mqtt
MQTTバージョン3.1.1:http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/
mqtt -v3.1.1-os.html