Understanding NetworkStream.EndRead () - an example from MSDN

I tried to understand the MSDN example for NetworkStream.EndRead (). There are some parts that I do not understand.

So here is an example (copied from 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); } 

It uses BeginRead () and EndRead () to asynchronously read from a network stream. All this is caused by a call.

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

elsewhere (not shown in the example).

I think that this needs to be done, this is to print all the message received from NetworkStream in one WriteLine (the one that is at the end of the example). Note that the string is called myCompleteMessage .

Now, when I look at the implementation, some problems arise for my understanding.

First of all: in the example, a new method, the local buffer myReadBuffer . Then EndStream () is called, which writes the received message to the buffer that was sent to BeginRead (). This is NOT the myReadBuffer that has just been allocated. How should a network stream know about this? Therefore, in the next line, numberOfBytesRead -bytes from the empty buffer are added to myCompleteMessage . Which has the current value "" . On the last line, this message, consisting of a large number of '\0' , is printed using Console.WriteLine .

That makes no sense to me.

The second thing I don’t understand is while -loop.

BeginRead is an asynchronous call. Therefore, data is not immediately read. So, as I understand it, the while loop should run quite a while until some asynchronous call is made and read from the stream, so there is no more data. The documentation does not say that BeginRead immediately notes that part of the available data is being read, so I do not expect this to be done.

This example does not improve my understanding of these methods. Is this example wrong or is my understanding wrong (I expect the latter)? How does this example work?

+6
source share
1 answer

I think that while loop around BeginRead should not be there. You do not want to execute BeginRead more than before EndRead completes. In addition, the buffer must be specified outside of BeginRead, because you can use more than one read for each packet / buffer.

There are some things you need to think about, such as how long my messages / blocks are (fixed size). Should I prefix its length. (variable size) <datalength><data><datalength><data>

Do not forget that this is a streaming connection, so several / partial messages / packets can be read in one reading.

Pseudo example:

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

Source: https://habr.com/ru/post/955009/


All Articles