2013-10-01 23 views
5

Ho cercato di capire l'esempio MSDN per NetworkStream.EndRead(). Ci sono alcune parti che non capisco.Informazioni su NetworkStream.EndRead() - esempio da MSDN

ecco l'esempio (copiato da 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); 
} 

utilizza BeginRead() e EndRead() per leggere in modo asincrono dal flusso di rete. Il tutto viene richiamato chiamando

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

da qualche altra parte (non visibile nell'esempio).

Quello che penso che dovrebbe fare è stampare l'intero messaggio ricevuto da NetworkStream in una sola WriteLine (quella alla fine dell'esempio). Si noti che la stringa è denominata myCompleteMessage.

Ora, quando guardo l'implementazione, alcuni problemi sorgono per la mia comprensione.

Prima di tutto: l'esempio alloca un nuovo buffer locale metodo myReadBuffer. Quindi viene chiamato EndStream() che scrive il messaggio ricevuto nel buffer fornito da BeginRead(). Questo NON è il myReadBuffer che è stato appena assegnato. Come dovrebbe sapere il flusso di rete? Quindi la riga successiva numberOfBytesRead -bytes dal buffer vuoto vengono aggiunti a myCompleteMessage. Quale ha il valore attuale "". Nell'ultima riga questo messaggio costituito da un sacco di '\0' s viene stampato con Console.WriteLine.

Questo non ha alcun senso per me.

La seconda cosa che non capisco è lo while -loop.

BeginRead è una chiamata asincrona. Quindi nessun dato viene immediatamente letto. Quindi, a quanto ho capito, il ciclo while dovrebbe durare un po 'finché una chiamata asincrona non viene effettivamente eseguita e viene letta dal flusso in modo che non ci siano più dati disponibili. La documentazione non dice che BeginRead segna subito una parte dei dati disponibili come la lettura, quindi non mi aspetto che faccia così.

Questo esempio non migliora la mia comprensione di questi metodi. Questo esempio è sbagliato o la mia comprensione è sbagliata (mi aspetto quest'ultimo)? Come funziona questo esempio?

+2

L'esempio è solo sbagliato. Davvero sbagliato. –

risposta

5

Penso che il mentre il ciclo intorno al BeginRead non dovrebbe essere lì. Non si desidera eseguire BeginRead più di prima che l'EndRead sia terminato. Anche il buffer deve essere specificato all'esterno di BeginRead, poiché è possibile utilizzare più di un read per pacchetto/buffer.

Ci sono alcune cose a cui devi pensare, ad esempio quanto tempo sono i miei messaggi/blocchi (dimensione fissa). Devo prefisso con una lunghezza. (dimensioni variabili)<datalength><data><datalength><data>

Non dimenticate che è una connessione in streaming, in modo che più/messaggi parziali/pacchetti possono essere letti in una lettura.

Pseudo esempio:

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

sì, questo ha più senso per me – jsf