0

私の状況

シリアル化され、base64 にエンコードされた大きなオブジェクトを接続経由で送信する TCP ネットワーク プログラムがあります。私はクライアント ライブラリとサーバー ライブラリを作成しましたが、どちらも と を使用NetworkStream's Begin/EndReadしていBegin/EndWriteます。私が使用している(非常に単純化されたバージョンの)コードは次のとおりです。

サーバーの場合:

var Server = new TcpServer(/* network stuffs */);
Server.Connect();
Server.OnClientConnect += new ClientConnectEventHandler(Server_OnClientConnect);

void Server_OnClientConnect()
{
    LargeObject obj = CalculateLotsOfBoringStuff();
    Server.Write(obj.SerializeAndEncodeBase64());
}

次に、クライアント:

var Client = new TcpClient(/* more network stuffs */);
Client.Connect();
Client.OnMessageFromServer += new MessageEventHandler(Client_OnMessageFromServer);

void Client_OnMessageFromServer(MessageEventArgs mea)
{
    DoSomethingWithLargeObject(mea.Data.DecodeBase64AndDeserialize());
}

クライアント ライブラリには、を介してデータを文字列として渡すNetworkStream.BeginReadイベントをトリガーするコールバック メソッドがあります。OnMessageFromServerMessageEventArgs

私の問題

ただし、を介して大量のデータを受信BeginRead/EndReadすると、複数のメッセージに断片化されているように見えます。EG これは長いメッセージのふりをします:

"This is a really long message except not because it's for explanatory purposes."

それが本当に長いメッセージだった場合、Client_OnMessageFromServer呼び出される可能性があります...「長いメッセージ」の断片化された部分で3回言ってください:

"This is a really long messa"

"ge except not because it's for explanatory purpos"

"es."

すぅぅぅぅ……深呼吸

Begin/EndWriteへの 1 回の呼び出しですべてを 1 つに送信して受信するには、どのような方法が最適でしょうClient_OnMessageFromServerか?

4

2 に答える 2

6

できません。TCP では、物事がどのように到着するかは、送信された方法と必ずしも同じではありません。完全なメッセージを構成するものを把握し、必要に応じて完全なメッセージが得られるまで受信データをバッファリングするはコードの仕事です (処理する次のメッセージの開始を破棄しないように注意してください)。

テキストプロトコルでは、これは通常「改行/ヌル文字を見つける」ことを意味します。バイナリの場合、通常は「メッセージのプリアンブルの長さヘッダーを読み取る」ことを意味します。

于 2012-08-12T23:13:43.420 に答える
4

TCP はストリーム プロトコルであり、固定のメッセージ境界がありません。これは、メッセージの一部、またはメッセージの終わりと別のメッセージの始まりを受信できることを意味します。

これを解決するには、次の 2 つの方法があります。

  1. プロトコルを変更して、メッセージの終わりのマーカーを追加します。このようにして、特別なマーカーが見つかるまで継続して受け取ります。ただし、これにより、あるメッセージの終わりと別のメッセージの始まりを含むバッファーが作成される可能性があるため、次の方法をお勧めします。
  2. 最初にメッセージの長さを送信するようにプロトコルを変更します。そうすれば、メッセージの長さが正確にわかり、受信中にカウントダウンできるので、次のメッセージの冒頭を読む必要がありません。
于 2012-08-12T23:17:59.403 に答える