简体   繁体   中英

Read buffer from NetworkStream in async callback

See also Understand the NetworkStream.EndRead() example from MSDN .

I'm trying to read asynchronously from a NetworkStream using the BeginRead and EndRead methods (specifically, I want to open a NetworkStream, do various other tasks, then process the data that's been received on the NetworkStream). The MSDN example for EndRead ( here ) has various issues and doesn't work as it stands, as noted in the linked question. The answer to that question shows how the basic code should be structured, but it doesn't include the actual reading of the data from the NetworkStream in the callback.

In the callback function, how do I transfer the data that's been read from the NetworkStream into a buffer?

EDIT

This is the original MSDN example.

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);
}

The basic problem with this example is that no data is transferred from the NetworkStream to myReadBuffer .

EDIT 1

Thanks to Dmytro Mukalov, the following code works:

internal class CallbackArgs
{
    public NetworkStream Stream { get; set; }
    public byte[] Buffer { get; set; }

    public CallbackArgs(NetworkStream stream, byte[] buffer)
    {
        Stream = stream;
        Buffer = buffer;
    }
}

//  In the caller:

    //  (Create and open thisNetworkStream, and check thisNetworkStream.CanRead)

    byte[] thisReadBuffer = new byte[1024];
    CallbackArgs args = new CallbackArgs(thisNetworkStream, thisReadBuffer);
    thisNetworkStream.BeginRead(thisReadBuffer, 0, thisReadBuffer.Length, new AsyncCallback(myReadCallBack), args);

//  The callback function:
public static void myReadCallBack(IAsyncResult ar)
{
    CallbackArgs args = (CallbackArgs)ar.AsyncState;
    NetworkStream myNetworkStream = args.Stream;
    byte[] myReadBuffer = args.Buffer;

    //  myReadBuffer now contains the data read from the network stream.

    int bytesRead = myNetworkStream.EndRead(ar);

    //  Do work on myReadBuffer, etc.
}

When callback is being executed, data is already transferred into a buffer passed to preceding BeginRead call. The problem with given example that it's trying to use local myReadBuffer buffer to read initial message. Instead you should make the buffer passed to BeginRead availaible for EndRead . You can do it by making it instance member of a class for this buffer, by passing it along with NetworkStream as state argument of BeginRead , using closure variable in some method which would initiate the reading loop, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM