MQTT CONNECTメッセージのクライアントIDのみを変更する方法は?


8

MQTT CONNECTメッセージをいじっています。私のラップトップで実行されているMosquittoブローカーに向けてTCP / IPソケットを開き、MQTT CONNECTメッセージを送信し、(通常)4バイト長のCONNACK応答を受信して​​ソケットを閉じ、プログラムを終了する単純なCプログラムがあります。

現在、私は自分のCONNECTメッセージを作成していませんが、Wiresharkキャプチャからのものを使用しています。

Wiresharkキャプチャのスクリーンショット

MQTTパーツであるC配列としてエクスポートできます。

char packet_bytes[] = {
  0x10, 0x20, 0x00, 0x06, 0x4d, 0x51, 0x49, 0x73,
  0x64, 0x70, 0x03, 0x02, 0x00, 0x3c, 0x00, 0x12,
  0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x31, 0x34, 0x38,
  0x35, 0x38, 0x39, 0x30, 0x38, 0x35, 0x37, 0x31,
  0x39, 0x34
};

この変更されていない配列を使用すると、すべてがうまく機能します。ブローカーの出力は次のとおりです。

1486237905: New connection from 192.168.1.2 on port 1883.
1486237905: New client connected from 192.168.1.2 as root.1485890857194 (c1, k60).
1486237905: Sending CONNACK to root.1485890857194 (0, 0)
1486237905: Socket error on client root.1485890857194, disconnecting.

メッセージのクライアントIDを変更するときに問題が発生します。私の最も簡単な試みは4、IDの最後から最後の文字を切り刻むことです。

これには、実際のコードに3つの変更が必要だと思います。

  1. 配列の最後のバイトを削除します0x34
  2. Remaining Lengthメッセージのフィールド(配列の2番目のバイト)をデクリメントします。したがって、32から31まで0x20-> 0x1F
  3. send関数のバイト数パラメーターのデクリメント。34から33まで(+ フィールドHeader FlagsRemaining Lengthフィールドのため+2 )

char packet_bytes[] = {
  0x10, 0x1F, 0x00, 0x06, 0x4d, 0x51, 0x49, 0x73,
  0x64, 0x70, 0x03, 0x02, 0x00, 0x3c, 0x00, 0x12,
  0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x31, 0x34, 0x38,
  0x35, 0x38, 0x39, 0x30, 0x38, 0x35, 0x37, 0x31,
  0x39
};


if( send(s , packet_bytes , 33, 0) < 0)
{
    puts("Send failed");
    return 1;
}

動作しません。ブローカーの出力は次のとおりです。

1486239491: New connection from 192.168.1.2 on port 1883.
1486239491: Socket error on client <unknown>, disconnecting.

私はRemaining Lengthフィールドが特別なencondingを必要とすることを知っていますが、128未満ではありません。

残りの長さ表

ここで見逃したものは何Remaining Lengthですか。フィールドの横で何を変更する必要がありますか?


ブローカーはソケットエラーコードなどをログに記録しませんか?
Aurora0001

@ Aurora0001実際には、詳細なコンソールロギングで十分だと思ったので、確認しませんでした。私はそれをチェックします、私は窓の下でログファイルを見つけなければなりません。
Bence Kaulics 2017

1
@ Aurora0001実際、クライアント側で間違いを見つけるのに忙しかったので、詳細なサーバーログを検索することは考えていなかったので、指摘してくれてありがとう。何か見つけたら更新します。
Bence Kaulics 2017

現在、追加のログはありません。
Bence Kaulics

1
@ Aurora0001いいえ、データは送信されます。この場合のみ、CONACKを受信しません。recv関数は0を返し、プログラムは終了します。その時はキャプチャーしてみます。
Bence Kaulics 2017

回答:


5

なんとか間違いを見つけました。誤って、クライアントIDは修正フィールドであると想定しましたが、これはメッセージのペイロードの一部にすぎないため、長さのプレフィックスが必要です。仕様から:

CONNECTパケットのペイロードには、1つ以上の長さの接頭辞が付いたフィールドが含まれています。その存在は、可変ヘッダーのフラグによって決定されます。これらのフィールドが存在する場合、クライアント識別子、ウィルトピック、ウィルメッセージ、ユーザー名、パスワードの順に表示する必要があります。

そのため、メッセージでさらに1バイトを減らす必要があります。正しい手順:

  1. 配列の最後のバイト、0x34を削除します。
  2. メッセージのRemaining Lengthフィールド(配列の2番目のバイト)をデクリメントします。したがって、32から31までは0x20-> 0x1Fです。
  3. ペイロード内のクライアントIDの長さプレフィックスバイトをデクリメントします。私の場合、これは16番目のバイト(1から数えて)0x12---> 0x11です。
  4. 送信関数のバイト数パラメーターを減らします。34から33まで。(+ 2ヘッダーフラグと残りの長さフィールドのため)

この追加のステップの後、ブローカーはCONNACKメッセージを送り返しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.