2013-10-01 18 views
5

Ich habe versucht, das MSDN-Beispiel für NetworkStream.EndRead() zu verstehen. Es gibt einige Teile, die ich nicht verstehe.Verstehen der NetworkStream.EndRead() - Beispiel von MSDN

So, hier ist das Beispiel (kopiert von 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); 
} 

Es verwendet Beginread() und EndRead() asynchron aus dem Netzwerk-Stream zu lesen. Das Ganze wird durch den Aufruf aufgerufen

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

woanders (im Beispiel nicht angezeigt).

Was ich denke, es sollte die gesamte Nachricht aus dem NetworkStream in einer einzigen WriteLine drucken (die am Ende des Beispiels). Beachten Sie, dass die Zeichenfolge myCompleteMessage heißt.

Jetzt, wenn ich auf die Implementierung schaue, entstehen einige Probleme für mein Verständnis.

Zunächst einmal: Das Beispiel weist eine neue Methode zu - lokaler Puffer . Dann wird EndStream() aufgerufen, der die empfangene Nachricht in den Puffer schreibt, der mit BeginRead() geliefert wurde. Dies ist NICHT die myReadBuffer, die gerade zugewiesen wurde. Wie sollte der Netzwerk-Stream davon wissen? Also in der nächsten Zeile numberOfBytesRead -bytes aus dem leeren Puffer an myCompleteMessage angehängt werden. Welches hat den aktuellen Wert "". In der letzten Zeile wird diese Nachricht, die aus einer Menge von '\0' s besteht, mit gedruckt.

Das ergibt für mich keinen Sinn.

Die zweite Sache, die ich nicht verstehe, ist die while -loop.

BeginRead ist ein asynchroner Aufruf. So werden keine Daten sofort gelesen. So wie ich es verstehe, sollte die while-Schleife eine ganze Weile laufen, bis ein asynchroner Aufruf tatsächlich ausgeführt wird und aus dem Stream liest, so dass keine Daten mehr verfügbar sind. Die Dokumentation sagt nicht, dass BeginRead sofort einen Teil der verfügbaren Daten als gelesen markiert, also erwarte ich das nicht.

Dieses Beispiel verbessert nicht mein Verständnis dieser Methoden. Ist dieses Beispiel falsch oder ist mein Verständnis falsch (ich erwarte das letztere)? Wie funktioniert dieses Beispiel?

+2

Das Beispiel einfach falsch ist. Wirklich falsch. –

Antwort

5

Ich denke, die While-Schleife um das BeginRead sollte nicht da sein. Sie möchten das BeginRead nicht mehr als nur vor dem EndRead ausführen. Außerdem muss der Puffer außerhalb von BeginRead angegeben werden, da Sie mehr als einen Lesevorgang pro Paket/Puffer verwenden können.

Es gibt einige Dinge, über die Sie nachdenken müssen, wie lange sind meine Nachrichten/Blöcke (feste Größe). Soll ich ihm eine Länge voranstellen? (variable Größe)<datalength><data><datalength><data>

Vergessen Sie nicht, es ist eine Streaming-Verbindung, so dass mehrere/teilweise Nachrichten/Pakete in einem gelesen werden können.

Pseudo Beispiel:

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(); 
} 
+0

Ja das macht mehr Sinn für mich – jsf