3

これは、統合セットアップに関する私の質問に関連しています (永続的なチャネルを使用したポートの統合)

プロトコルのすべてのトラフィックにプレフィックスを付けた 2 バイト シーケンスを送信しようとしています。私はこれを行っているので、複数のプロトコルをサポートするように更新するときに、統合ハンドラーで盗聴するものがあります。

クライアントでは、パイプラインの最後に、バイトを識別する 2 つのプロトコルを ByteBuf の前に付けるシンプルなアウトバウンド ハンドラーと、それらを抽出するサーバー パイプラインの前にシンプルなインバウンド ハンドラーがあります。これを小さなメッセージで機能させることができました。

サーバー キュー内の後続のハンドラーはLengthFieldBasedFrameDecoder、着信トラフィック (protobuf オブジェクト) をフレーム化するために使用している です。発生しているように見えるのは、クライアントが 5M などの大きなリクエストを送信していることです。サーバーパイプラインを通過する一連の 64k バッファーを取得します。最後のバッファーは、LengthFieldBasedFrameDecoder待機しているしきい値を超え、フレームを抽出して処理のために渡します。これは正しく行われます。

この時点で、すべてが壊れます。私が知る限り、クライアントからの最後の 64k バッファーには、フレームの残りのデータ、次の要求の開始を知らせる 2 バイト シーケンス、およびその他のコンテンツが含まれていました。このデータはフレーム デコーダーにあると思いますが、これは次のフレームの長さとして 2 つのプロトコル マジック バイトを使用しますが、これは誤りであり、そこから問題が発生します。

このDelimiterBasedFrameDecoder場合、その 2 バイト シーケンスは各論理フレーム/リクエストを分割するため、うまくいくように見えますが、このシナリオではやり過ぎのように思えます。

この場合に機能する他のデコーダーはありDelimiterBasedFrameDecoderますか?

4

3 に答える 3

3

LengthFieldBasedFrameDecoderのドキュメントに目を通してみると、あなたがやろうとしていることを行う方法の素晴らしい例があります。4 番目の例では、長さフィールドの前に固定幅のヘッダーがあり、ヘッダー情報を削除しないように FrameDecoder を構成しています。

編集

サーバーの場合、LengthFieldBasedFrameDecoder が最初に来る必要があります。次に、ヘッダーをチェックするハンドラーがヘッダーと長さフィールドを削除し、それに応じてデータを渡すことができます。

クライアント側では、LengthFieldPrependerを使用し、その後に追加のハンドラーを追加して、ヘッダー データを先頭に追加できます。

于 2013-08-27T20:19:57.647 に答える
0

通常、長さフィールド フレーム デコーダーを使用している場合は、フレーム ハンドラーの前に行く SSL または圧縮ハンドラーも使用していない限り、パイプラインの最初にある必要があります。最も簡単な解決策は、プロトコル ID ハンドラーをフレーム ハンドラーの前ではなく後に配置することです。

于 2013-08-26T23:28:10.857 に答える
0

DelimiterBasedFrameDecoder、この状況で大まかに必要なものですが、区切り文字がフレームの最後ではなく前にあることを処理しないため、この場合に使用すると、基本的にトラフィックが消費されます。

indexOfメソッドDelimitedBasedFrameDecoderを使用すると、サーバー チャネルで使用する非常に単純なデコーダをまとめて、デリミタを食べながら、デリミタ シーケンスによって着信トラフィックを分割できます。

public static final class DelimitingProtocolDecoder extends ByteToMessageDecoder {
    private final ByteBuf mDelimiter;

    public DelimitingProtocolDecoder(final ByteBuf theDelimiter) {
        mDelimiter = theDelimiter;
    }

    @Override
    protected void decode(final ChannelHandlerContext theContext, final ByteBuf theInput, final List<Object> theOutput) throws Exception {
        int aIndex = indexOf(theInput, mDelimiter);

        while (aIndex != -1) {
            if (aIndex > 0) {
                ByteBuf aBuffer = theContext.alloc().buffer(aIndex, aIndex);

                theInput.readBytes(aBuffer);

                theOutput.add(aBuffer);
            }

            theInput.skipBytes(mDelimiter.capacity());

            aIndex = indexOf(theInput, mDelimiter);
        }

        theOutput.add(theInput.readBytes(theInput.readableBytes()));
    }
}
于 2013-08-27T13:34:16.417 に答える