Can someone explain this code snippet from MSDN (NetworkStream.EndRead)..

cjard

Well-known member
Joined
Apr 25, 2006
Messages
7,081
Programming Experience
10+
in the following code:

VB.NET:
[COLOR=blue]Public[/COLOR] [COLOR=blue]Shared[/COLOR] [COLOR=blue]Sub[/COLOR] myReadCallBack(ar [COLOR=blue]As[/COLOR] IAsyncResult)
 
   [COLOR=blue]Dim[/COLOR] myNetworkStream [COLOR=blue]As[/COLOR] NetworkStream = CType(ar.AsyncState, NetworkStream)
   [COLOR=blue]Dim[/COLOR] myReadBuffer(1024) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte[/COLOR]
   [COLOR=blue]Dim[/COLOR] myCompleteMessage [COLOR=blue]As[/COLOR] [String] = [COLOR=maroon]""[/COLOR]
   [COLOR=blue]Dim[/COLOR] numberOfBytesRead [COLOR=blue]As[/COLOR] [COLOR=blue]Integer[/COLOR]
 
   numberOfBytesRead = myNetworkStream.EndRead(ar)
   myCompleteMessage = [String].Concat(myCompleteMessage, Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead))
 
   [COLOR=green]' message received may be larger than buffer size so loop through until you have it all.[/COLOR]
   [COLOR=blue]While[/COLOR] myNetworkStream.DataAvailable
 
      myNetworkStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length, [COLOR=blue]New[/COLOR] AsyncCallback([COLOR=blue]AddressOf[/COLOR] NetworkStream_ASync_Send_Receive.myReadCallBack), myNetworkStream)
   [COLOR=blue]End[/COLOR] [COLOR=blue]While[/COLOR]
 
 
   [COLOR=green]' Print out the received message to the console.[/COLOR]
   Console.WriteLine(([COLOR=maroon]"You received the following message : "[/COLOR] + myCompleteMessage))
[COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR] [COLOR=green]'myReadCallBack[/COLOR]
 
[COLOR=green]'Entry point which delegates to C-style main Private Function[/COLOR]
[COLOR=blue]Public[/COLOR] [COLOR=blue]Overloads[/COLOR] [COLOR=blue]Shared[/COLOR] [COLOR=blue]Sub[/COLOR] Main()
   Main(System.Environment.GetCommandLineArgs())
[COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR]


my confusion is in red, below:

VB.NET:
[COLOR=blue]Public[/COLOR] [COLOR=blue]Shared[/COLOR] [COLOR=blue]Sub[/COLOR] myReadCallBack(ar [COLOR=blue]As[/COLOR] IAsyncResult)
 
   [COLOR=blue]Dim[/COLOR] myNetworkStream [COLOR=blue]As[/COLOR] NetworkStream = CType(ar.AsyncState, NetworkStream) [B][COLOR=red]'convenience variable, accessing the network stream in an async call[/COLOR][/B]
   [COLOR=blue]Dim[/COLOR] myReadBuffer(1024) [COLOR=blue]As[/COLOR] [COLOR=blue]Byte [B][COLOR=#ff0000]'establish a pointer to a buffer to read data into - where does this point to? Nothing?[/COLOR][/B][/COLOR]
   [COLOR=blue]Dim[/COLOR] myCompleteMessage [COLOR=blue]As[/COLOR] [String] = [COLOR=maroon]"" [B][COLOR=#ff0000]'make an empty string[/COLOR][/B][/COLOR]
   [COLOR=blue]Dim[/COLOR] numberOfBytesRead [COLOR=blue]As[/COLOR] [COLOR=blue]Integer[/COLOR]
[B][COLOR=#ff0000][/COLOR][/B] 
[B][COLOR=#ff0000]    'tell the async executing NS to finish reading data into some internal [/COLOR][/B]
[B][COLOR=#ff0000]    'buffer, it tells us how many bytes it read[/COLOR][/B]
   numberOfBytesRead = myNetworkStream.EndRead(ar) 
 
[B][COLOR=#ff0000]    'take our NullReference byte array of 1024 bytes and [/COLOR][/B]
[B][COLOR=#ff0000]    'tack it onto the end of our empty string.[/COLOR][/B]
[B][COLOR=#ff0000]    'at this point we have an empty byte array and a string made of [/COLOR][/B]
[B][COLOR=#ff0000]    'the concatenation of an empty string and a null reference[/COLOR][/B]
   myCompleteMessage = [String].Concat(myCompleteMessage, Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead)) 
[B][COLOR=#ff0000][/COLOR][/B]

   [COLOR=green]' message received may be larger than buffer size so loop through until you have it all.[/COLOR]
   [COLOR=blue]While[/COLOR] myNetworkStream.DataAvailable
      [B][COLOR=#ff0000]'async setup to call this method again, this isnt quite recursion?[/COLOR][/B]
[B][COLOR=#ff0000]      ' presumably at this point the re-call manages to populate some[/COLOR][/B]
[B][COLOR=#ff0000]      ' data into the byte array? is myReadBuffer passed ByRef? [/COLOR][/B]
      myNetworkStream.BeginRead(myReadBuffer, 0, myReadBuffer.Length, [COLOR=blue]New[/COLOR] AsyncCallback([COLOR=blue]AddressOf[/COLOR] NetworkStream_ASync_Send_Receive.myReadCallBack), myNetworkStream)
   [COLOR=blue]End[/COLOR] [COLOR=blue]While[/COLOR]
 
 
   [COLOR=green]' Print out the received message to the console.[/COLOR]
[COLOR=#ff0000][B]    'how does this method print anything other than a string of nothing? does [/B][/COLOR]
[COLOR=#ff0000][B]    'concatting a reference to nothing onto a string give us the ability to modify [/B][/COLOR]
[COLOR=#ff0000][B]    'the string content? i'm lost now[/B][/COLOR]
   Console.WriteLine(([COLOR=maroon]"You received the following message : "[/COLOR] + myCompleteMessage)) 
[COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR] [COLOR=green]'myReadCallBack[/COLOR]
 
[COLOR=green]'Entry point which delegates to C-style main Private Function[/COLOR]
[COLOR=blue]Public[/COLOR] [COLOR=blue]Overloads[/COLOR] [COLOR=blue]Shared[/COLOR] [COLOR=blue]Sub[/COLOR] Main()
   Main(System.Environment.GetCommandLineArgs())
[COLOR=blue]End[/COLOR] [COLOR=blue]Sub[/COLOR]


how does this code read anything out of a network stream? it seems to do things backwards?
 
Does that code work? I'm with you I think. It appears that the "myCompleteMessage=[...]" should be -after- the "myNetworkStream.BeginRead...

I dont get how myCompleteMessage would contain any data unless I'm overlooking something as well..
 
The "... As [String]" looks like a joke, but the byte array was filled from the BeginRead call that resulted in this read callback. You have to read the first part of the story too, the docs for this topic says "The EndRead method completes the asynchronous read operation started in the BeginRead method." So just click on the linked BeginRead topic to see the start. It is just a BeginRead call, nothing more, but that is also the key to where the bytes start to read. When this read callback call BeginRead again to get more data it isn't recursive, but just the async way to continue reading the stream of data.
 
So there's a pair of methods for begin and end (this was passed to me by a third party - thought i'd ask you gurus) and they flip/flop between each other.. Do tell me, for I am curious, how they can colelctively read and write data?

How can an array Dimmed in this method become filled/be the array dimmed in another method? Is it byreffed, and both the read and the write arrays passed into the same network stream are pointed to the same thing?

John, as you seem to understand it, could you provide a higher level storyboard of what is going on, because it looks like a highly curious and not-very-OO way of doing things? I this example written by an C++ aficionado?
 
It's straight from the NetworkStream.BeginRead / EndRead documentation. When I have used this I have declared the buffer global for common access of both methods.
 
That (a class-level buffer declaration), I would understand.. But these are local method-level declarations of the buffer. What is my understanding missing?
 
As i understand it the buffer does point to an unmanaged pinnedarray but it is always passed byval. From what i can see the buffer should be retrieved from the AsyncResult.AsyncState i can't see where the buffer contains any information here. MyCompleteMessage would appear to be in the right place but it looks like there is a mistake in that article to me.
 
Back
Top