2

固定サイズのヘッダーと可変長のペイロードを持つ一連のメッセージで構成される比較的単純なプロトコルを使用して、TCP/IP 経由でデバイスと通信する C# アプリケーションがあります。ヘッダーにはペイロードの長さが含まれます。

最近、プログラミング モデルを同期から非同期に変更しましたが、興味深い問題が発生しました。それは、部分的に受信したメッセージをどのように処理するかということです。

同期コード

public void ReceiveMessage(NetworkStream stream)
{
    // Read the header from the stream
    MessageHeader header = stream.ReadHeader();

    int payloadBytesRead = 0;
    byte[] buffer = new byte[header.PayloadSize];

    // Keep reading from the stream until the payload
    // is fully extracted
    while (payloadBytesRead < header.PayloadSize)
    {
        payloadBytesRead += stream.Read(buffer, payloadBytesRead, header.PayloadSize - payloadBytesRead);
    }

    MessagePayload = new MessagePayload(buffer);

    // Do something with the message here
    // ...

}

whereは、ストリームから固定サイズのヘッダーを抽出するためReadHeaderの拡張メソッドです。NetworkStream

非同期バージョンの問題

BeginReadとを使用する非同期バージョンではEndRead、バッファ内の部分的に受信されたメッセージで読み取りコールバックが呼び出される可能性があります。データがストリームからプルされた後にコールバックが呼び出されるため、次のコールバックのために部分的なメッセージをストリームに残すことはできません。ただし、後で処理できるように、次のコールバックまでこの部分的なデータを保持する必要があります。

唯一の解決策は、部分的なデータ バイトを別のバッファにコピーするか、次のバッファBeginReadが呼び出される前に受信バッファの一番下にシフトすることです。これは正しいですか、またはこのシナリオを処理するためのより一般的な手法はありますか?

4

0 に答える 0