2

この仕様でJava を使用して BitTorent プロトコルを実装しています。メッセージ セクションでは、2 つのメッセージを除いてすべてのメッセージが固定長です。そのうちの 1 つは、ハンドシェイク後の唯一の可変メッセージであるため、他のメッセージを確認して、他のメッセージが一致しなかった場合に、それがピース メッセージであると想定できます。しかし、次のメッセージについては

bitfield: <len=0001+X><id=5><bitfield>

ビットフィールド メッセージは、ハンドシェーク シーケンスが完了した直後で、他のメッセージが送信される前にのみ送信できます。これはオプションであり、クライアントにピースがない場合は送信する必要はありません。

ビットフィールド メッセージは可変長で、X はビットフィールドの長さです。ペイロードは、正常にダウンロードされた部分を表すビットフィールドです。最初のバイトの上位ビットはピース インデックス 0 に対応します。クリアされたビットは欠落ピースを示し、セットされたビットは有効で利用可能なピースを示します。最後の予備ビットはゼロに設定されます。

間違った長さのビットフィールドはエラーと見なされます。正しいサイズでないビットフィールドを受信した場合、またはビットフィールドに予備のビットが設定されている場合、クライアントは接続をドロップする必要があります。

長さがわからないと解析する方法が思いつきません。バイトストリームで id を見つけるにはどうすればよいですか?

編集: ビットフィールド メッセージのペイロードでは、トレント ファイル内の各ピースの 0 または 1 であり、トレント コンテンツのサイズに応じてメッセージの長さが変わります。したがって、ピースの数が常に5バイトの数値に収まるとは思えません。

4

4 に答える 4

4

フィールドは常に、フィールドidの 4 バイトに続く、メッセージの 5 番目のバイトになりlenます。次のようなことができます。

DataInputStream stream;

// ...

int    length  = stream.readInt();
byte   id      = stream.readByte();
byte[] payload = new byte[length - 1];

stream.readFully(payload);

すべてのメッセージは同じlen+idヘッダーを持っているため、実際にはどのメッセージでも機能するはずです。

編集:「だから、ピースの数が常に5バイトの数に収まるとは思えません。」

4 バイトの長さのフィールドは、ペイロードで最大 2^32-1 バイトを処理でき、1 バイトあたり 8 ビットで、34,359,738,360 ピースの余地があります。それで十分なはずです!:-)

于 2009-06-22T21:48:58.030 に答える
3

長さがわからないと解析する方法が思いつきません。

説明から判断すると、長さはメッセージの最初の 4 バイトで示されます。

バイトストリームで id を見つけるにはどうすればよいですか?

id は各メッセージの 5 番目のバイト、長さフィールドの直後にあるように見えます。したがって、前のメッセージの解析が完了したら、最初の 5 バイトを確認するだけで済みます。

于 2009-06-22T21:49:36.830 に答える
3

あなたが参照した仕様の前半で、私は次のように読みました。'。私はそれを次のように読みました:次の4バイトを読み取り、それらをintに変換すると、それがあなたの長さになるはずです。バイトから int への変換プロセスに慣れていない場合は、これに似たものを使用しまし

于 2009-06-22T21:51:59.023 に答える
1

仕様を詳しく読んだことはありませんが、可変長フィールドの長さや終了区切り文字を明示的に知らなければ、それを処理する方法もわかりません。おそらく、事前に (可変の) 長さが通知されることを示しているのではbitfield=<len=0001+X>ないでしょうか?

于 2009-06-22T21:46:08.473 に答える