0

Java のソケットから Google Protocol Buffer メッセージを読み取ろうとするコードがいくつかあります。ただし、me​​rgeDelimitedFrom() メソッドは、無効なデータを読み取った場合、またはソケット接続がリセットされた場合 (およびおそらくその他の理由)、IOException をスローする可能性があります。接続がリセットされた場合はループを終了したいのですが、それが無効なメッセージである場合は実行を続けたいと思います。1 つの考えとしては、ある種の例外カウンターを用意し、X 回連続して失敗した後に終了することですが、暗闇の中にいるのではなく、どのような種類のエラーが発生したかを把握できるようにしたいと考えていました。

これは基本的に私が持っているコードです:

while (m_Running)
{
    SomeMessage message = null;
    try
    {
        final Builder builder = SomeMessage.newBuilder();
        if (builder.mergeDelimitedFrom(m_InputStream))
        {
            message = builder.build();
        }
        else
        {
            // Google protocol buffers doesn't document it very well
            // but if mergeDelimietedFrom returns false then it has
            // reached the end of the input stream.  For a socket, no
            // more data will be coming so exit from the thread
            m_Running = false;
        }
    }
    catch (final IOException e)
    {
        // what should really be done here ???
    }
}
4

1 に答える 1

1

ただそれをしないでください。プロトコルバッファオブジェクトをソケットから直接読み取っている場合は、独自のアプリケーションプロトコルを効果的に定義しています。あなたがそれを正しく行うと思うよりも難しいです-アプリケーションプロトコルの設計についてのいくつかの問題の良い一般的な説明があります。フレーミングを理解することが重要です。つまり、あるメッセージが終了し、別のメッセージが開始する場所を決定します。

これは、 https: //developers.google.com/protocol-buffers/docs/techniquesでprotobufの発明者からのアドバイスにつながります。重要なアドバイスは次のとおりです。

1つのファイルまたはストリームに複数のメッセージを書き込みたい場合は、1つのメッセージがどこで終了し、次のメッセージがどこで開始するかを追跡するのはあなた次第です。

ストリームをメッセージに分割するフレーミングプロトコルを決定してから、ソケットの作業または読み取りを処理するカスタムソケットコードを記述し、各バイト配列に1つのメッセージが含まれていることがわかっているバイト配列に分割することをお勧めします。次に、最後にprotobufを使用して、各message-byte-arrayをオブジェクトに逆シリアル化します。IOExceptionprotobufデシリアライズがないことを保証します。

それでもIOExceptionsに対処する必要がありますが、バイト配列を読み取っているだけの下位レベルになり、エラーが発生したときに逆シリアル化されたデータの量を正確に知ることができます。

また、ソケットコードを支援するためにnettyのようなものを使用することを検討してください。

于 2012-09-29T01:37:54.523 に答える