1

単純な状況:

Socket 上のクライアントは、ファイル (データ) の一部 (たとえば、256 バイト) をbyte []サーバーに送信します。サーバーは非同期でデータを受信します。ファイル (データ) が完全に送信されたことを確認する方法は? (サーバ側)

データの受信を担当するサーバー側のコードは次のとおりです

public static void ReadCallback(IAsyncResult ar)
{
        String content = String.Empty;

        // Retrieve the state object and the handler socket
        // from the asynchronous state object.
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.workSocket;


        // Read data from the client socket. 
        int bytesRead = handler.EndReceive(ar);

        if (bytesRead > 0)
        {

            BinaryWriter writer = new BinaryWriter(File.Open(@"D:\test.png", FileMode.Append));

            writer.Write(state.buffer, 0, bytesRead);
            writer.Close();

            // All the data has been read from the 
            // client. Display it on the console.
            Console.WriteLine("Read {0} bytes from socket!",
                bytesRead);

            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
        }
}

いくつかの次のことを可能にする方法はありますか?

if (bytesRead > 0)
{

     ....
     if(state.buffer!=end of receive)
     {
     handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
         new AsyncCallback(ReadCallback), state);
     }

}

または、このbyte[]オブジェクトに何らかの情報 (<EOF>タグ付きの文字列など) を追加しようとするかもしれませんが、各ステップでこの情報を分析する必要があります。このチェックをもっと簡単に、そしてどのように行うことができますか? または別の方法を使用します...

4

1 に答える 1

0

これを行う唯一の方法は、すべてのメッセージの前に (特定のサイズの) ヘッダーを送信することです。したがって、各メッセージはヘッダーと本文で構成されている必要があります。データ ストリームは次のようになります。

[HEADER][BODY][HEADER][SOME BIGGER BODY][HEADER][SOME EXTRA BIG BODY]

前述したように、ヘッダーは特定のサイズである必要があり、メッセージの本文のサイズ (バイト単位) を含むいくつかのカスタム サービス フィールドを含める必要があります。あなたの場合、ヘッダーには本体サイズ、つまり int 値 (4 バイト) のみを含めることができます。受信プロセスは次のようになります。

  1. 4 バイト (ヘッダー) を受信します。
  2. ヘッダーから本文のサイズを取得します (ヘッダーを int に変換するだけです)。
  3. ヘッダーで指定されたバイト数を受信します (つまり、メッセージ本文を受信します)。
  4. メッセージ本文を処理します。
  5. 1に行きます。

複雑に思えるかもしれませんが、これが一般的な方法です。しかし、 Rx ライブラリを使用することでコードを簡素化できます。ソケットのいくつかの拡張メソッドを実装した後 (WhenReadExact の場合、実装はインターネット経由で簡単に見つけることができます。たとえば、こちら)、コードは次のようになります。

var whenFileReceived = from header in socket.WhenReadExact(4)
                       let bodySize = BitConverter.ToInt32(header)
                       from body in socket.WhenReadExact(bodySize)
                       select body;

whenFileReceived.Subscribe(
    file =>
    {
        // Handle file here
    });
于 2012-10-17T23:41:08.473 に答える