9

NetworkStream.EndRead() の MSDN の例を理解しようとしました。わからない部分もあります。

したがって、ここに例があります( MSDNからコピー):

// Example of EndRead, DataAvailable and BeginRead.

public static void myReadCallBack(IAsyncResult ar ){

    NetworkStream myNetworkStream = (NetworkStream)ar.AsyncState;
    byte[] myReadBuffer = new byte[1024];
    String myCompleteMessage = "";
    int numberOfBytesRead;

    numberOfBytesRead = myNetworkStream.EndRead(ar);
    myCompleteMessage = 
        String.Concat(myCompleteMessage, Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));    

    // message received may be larger than buffer size so loop through until you have it all.
    while(myNetworkStream.DataAvailable){

        myNetworkStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length, 
                                               new AsyncCallback(NetworkStream_ASync_Send_Receive.myReadCallBack), 
                                                   myNetworkStream);  

    }

    // Print out the received message to the console.
    Console.WriteLine("You received the following message : " +
                                myCompleteMessage);
}

BeginRead() と EndRead() を使用して、ネットワーク ストリームから非同期的に読み取ります。呼び出しによってすべてが呼び出されます

myNetworkStream.BeginRead(someBuffer, 0, someBuffer.Length, new AsyncCallback(NetworkStream_ASync_Send_Receive.myReadCallBack), myNetworkStream);  

別の場所 (例には表示されていません)。

NetworkStream から受信したメッセージ全体を単一の WriteLine (例の最後にあるもの) に出力する必要があると思います。文字列が と呼ばれることに注意してくださいmyCompleteMessage

ここで実装を見ると、理解のためにいくつかの問題が発生します。

まず第一に: この例では、新しいメソッド ローカル バッファーを割り当てmyReadBufferます。次に EndStream() が呼び出され、BeginRead() が提供されたバッファに受信したメッセージが書き込まれます。これは、myReadBuffer割り当てられたばかりの ではありません。ネットワークストリームはそれをどのように知る必要がありますか? したがって、次の行でnumberOfBytesReadは、空のバッファからのバイトが に追加されmyCompleteMessageます。現在の値を持っています""'\0'最後の行では、多数のs で構成されるこのメッセージが で出力されConsole.WriteLineます。

これは私には意味がありません。

私が理解していない 2 番目のことは、whileループです。

BeginRead非同期呼び出しです。したがって、データはすぐには読み取られません。私が理解しているように、whileループは、非同期呼び出しが実際に実行されてストリームから読み取られるまで、かなりの時間実行される必要があり、データが利用できなくなります。ドキュメントにはBeginRead、利用可能なデータの一部が読み取られているとすぐにマークされるとは書かれていないため、そうなるとは思いません。

この例では、これらの方法に対する私の理解は向上しません。この例は間違っていますか、それとも私の理解が間違っていますか (私は後者だと思います)? この例はどのように機能しますか?

4

1 に答える 1

6

BeginRead のwhile ループはそこにあるべきではないと思います。EndRead が完了する前に、BeginRead を複数回実行したくありません。また、パケット/バッファごとに複数の読み取りを使用する可能性があるため、BeginRead の外でバッファを指定する必要があります。

メッセージ/ブロックの長さ (固定サイズ)など、考慮する必要があることがいくつかあります。長さの前に付けましょうか。(可変サイズ) <datalength><data><datalength><data>

ストリーミング接続であることを忘れないでください。そのため、複数/部分的なメッセージ/パケットを 1 回の読み取りで読み取ることができます。

疑似例:

int bytesNeeded;
int bytesRead;

public void Start()
{
    bytesNeeded = 40; // u need to know how much bytes you're needing
    bytesRead = 0;

    BeginReading();
}

public void BeginReading()
{
    myNetworkStream.BeginRead(
        someBuffer, bytesRead, bytesNeeded - bytesRead, 
        new AsyncCallback(EndReading), 
        myNetworkStream);
}

public void EndReading(IAsyncResult ar)
{
    numberOfBytesRead = myNetworkStream.EndRead(ar);

    if(numberOfBytesRead == 0)
    {
        // disconnected
        return;
    }

    bytesRead += numberOfBytesRead;

    if(bytesRead == bytesNeeded)
    {
        // Handle buffer
        Start();
    }
    else
        BeginReading();
}
于 2013-10-01T10:04:08.177 に答える