3

TCPを介して実装された単純なプロトコルがあり、各メッセージは次のもので構成されていると仮定します。

  1. int指示データ長。
  2. 1で指定された長さのバイナリデータ。

そのようなメッセージを読んで、私は次のようなものが欲しいです:

int length = input.ReadInt();
byte[] data = input.ReadBytes(length);

使用中Socket.ReceiveまたはNetworkStream.Read使用可能なバイト数が読み取られます。バイトが使用可能ReadBytesになるまで呼び出しをブロックしたい。length

読み取りをループせずに、残りのデータを待機するオフセットで再起動することなく、これを行う簡単な方法はありますか?

実際のアプリケーションでは、読み取りはおそらく非同期またはバックグラウンドスレッドで実行する必要がありますが、今のところそれを無視しています。重要なことは、すべてのデータが利用可能になるまで読み取りが完了しないようにすることです。

編集

私は自分でデータをバッファリングできることを知っており、その方法も知っています。Receive次のオフセットで続くループです。私が求めているのは、そのようなループの再利用可能な実装があり、いかなる種類の独自のループも必要ないかどうかです(または、すべてのデータが利用可能になったときに終了する再利用可能な非同期実装)。

4

6 に答える 6

5

何か、どこかでループする必要があります。結局のところ、複数のソケット読み取りが必要になる可能性があります。

BinaryReader.Read要求した分だけ読み取られるか、ストリームの最後に到達するまでループし続けると思いますが、ストリームの最後に達した場合に例外をスローしたいと仮定して、私は個人的に書き込みます別の方法。結局のところ、1つの場所に実装して再利用するのは簡単です。

于 2011-07-22T16:50:07.627 に答える
0

次のリンクをご覧ください: http://blog.stephencleary.com/2009/04/tcpip-net-sockets-faq.html

このリンクでは、ソケットとライブラリに関する優れた情報を見つけることができます。

私が実装することを確認する 1 つのことは、ネットワークが悪くなったときにスタックしないようにするためのタイムアウト メカニズムです。

于 2011-07-22T16:59:06.903 に答える
0

yield ステートメントはこのシナリオにうまく適合するように思えます。

つまり、着信ストリームを監視するループがあり、各長さの数値に達すると、IEnumerable / foreach への「yield」を介して呼び出し元に制御を戻します。

おそらく、yield は、IEnumerable への代替デカップリングのイベントを介して信号を送ることができます。私は IEnumerable が便利だと思います。

于 2011-07-22T17:24:16.653 に答える
0

自分でデータをバッファリングする必要があります。read の仕様は、1 バイトからバッファ サイズまでの任意の量を読み取ることができるということです。

于 2011-07-22T16:45:05.420 に答える
0

Socket.Available待機中のタイトなループが気にならない場合は、トリックを行いますか?

http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.available%28VS.71%29.aspx

于 2011-07-22T16:44:24.943 に答える
-1

ええと、ループを書かなければならないような悪臭を放っていますが、誰かがこのフォーラムの投稿にループを入れてくれたら、それをすばやくカットアンドペーストできるのでよかったと思います...これが私のものでした(そして、私がしたいことむしろ時間的にはベースですが、それは単体テスト専用であり、シミュレートされたサーバーを制御するため、それほど気にしません+ Readメソッドを呼び出すときに、単体テストが失敗してスタックしたくありません)

        int numBytes = 0;
        int i = 0;
        while(numBytes != length)
        {
            numBytes += latestClient.Receive(body, numBytes, length-numBytes, SocketFlags.None);                
            if(i == 10000)
                throw new Exception("Could not read enough data.  read="+numBytes+" but expected="+length);
        }
于 2011-12-15T18:40:58.430 に答える