2013-10-01 1 views
5

j'ai essayé de comprendre l'exemple MSDN pour NetworkStream.EndRead(). Il y a des parties que je ne comprends pas.Comprendre le NetworkStream.EndRead() - exemple de MSDN

Voici donc l'exemple (copié à partir 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); 
} 

Il utilise BeginRead() et EndRead() pour lire de manière asynchrone à partir du flux de réseau. L'ensemble est invoquée en appelant

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

ailleurs (non dans l'exemple).

Ce que je pense qu'il devrait faire est d'imprimer le tout message reçu du NetworkStream en un seul WriteLine (celui à la fin de l'exemple). Notez que la chaîne est appelée myCompleteMessage.

Maintenant, quand je regarde la mise en œuvre des problèmes se posent pour ma compréhension.

d'abord: L'exemple alloue un nouveau tampon de méthode locale myReadBuffer. Puis EndStream() est appelé qui écrit le message reçu dans le tampon que BeginRead() a été fourni. Ce n'est pas le myReadBuffer qui vient d'être alloué. Comment le réseau devrait-il en être informé? Ainsi, dans la ligne suivante numberOfBytesRead -bytes à partir du tampon vide sont ajoutés à myCompleteMessage. Lequel a la valeur actuelle "". Dans la dernière ligne, ce message composé d'un lot de '\0' s est imprimé avec Console.WriteLine.

Cela n'a aucun sens pour moi.

La deuxième chose que je ne comprends pas le while -loop.

BeginRead est un appel asynchrone. Donc, aucune donnée n'est immédiatement lue. Donc, si je comprends bien, la boucle while devrait fonctionner assez longtemps jusqu'à ce que certains appels asynchrones soient exécutés et lisent à partir du flux afin qu'il n'y ait plus de données disponibles. La documentation ne dit pas que BeginRead marque immédiatement une partie des données disponibles comme étant lu, donc je ne m'attends pas à le faire.

Cet exemple n'améliore pas ma compréhension de ces méthodes. Cet exemple est-il faux ou ma compréhension est-elle fausse (je m'attends à ce dernier)? Comment fonctionne cet exemple?

+2

L'exemple est tout simplement faux. Vraiment mal. –

Répondre

5

Je pense que le alors que la boucle autour du BeginRead ne devrait pas être là. Vous ne voulez pas exécuter le BeginRead plus de ceux avant que le EndRead soit fait. Le tampon doit également être spécifié en dehors de BeginRead, car vous pouvez utiliser plusieurs lectures par paquet/tampon.

Il ya certaines choses que vous devez penser, comme la durée de mes messages/blocs (taille fixe). Dois-je préfixer avec une longueur. N'oubliez pas qu'il s'agit d'une connexion en streaming, de sorte que des messages/paquets multiples/partiels peuvent être lus en une seule lecture.

Pseudo exemple:

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

ouais cela me semble plus logique – jsf

Questions connexes