How async Socket.EndReceive know the number of bytes it read? And how does async socket finish reading?

StackOverflow https://stackoverflow.com/questions/23650260

Question

I have this code

_socket.BeginReceive(
        _buffer, 
        0, 
        _buffer.Length, 
        SocketFlags.None, 
        _asyncCallback, 
        sSocketName);

**with**
_buffer.Length = 262144;
_asyncCallback = OnReceive;
sSocketName is a state string object (sSocketName = "History")

And the AsynCallback delegate method:

private void OnReceive(IAsyncResult asyn)
{
    if (asyn.AsyncState.ToString().Equals("History"))
    {
       int receivedBytes = _socket.EndReceive(asyn);
       string data = Encoding.ASCII.GetString(_buffer, 0, receivedBytes);
       //...
    }
    //...
}

receivedBytes is an integer which indicate the number of received bytes. In my case, it is around 23,000 -> 25,000.

The socket server is an internet server which keep pushing raw data to my client socket in term of string message, and it has much more more than 25,000 bytes of data.

So my question:

  1. What determine the number of received bytes?
  2. And What determine if the receiving is finished?
Was it helpful?

Solution

The async callback is not necessarily triggered when a "complete" message is send. It reads as much bytes as are available. Only you can determine if all data has been received. So if you're sending the string "Hello World", it's a perfectly valid scenario to first receive "Hell", on one callback, and "o World" on the next.

You'll have to determine what the length of the message is yourself, by rolling you're own protocol, for instance by prepending the message you're sending with the length of the data to be sent.

As a simple example, assume chars are one byte, maximum message length is 255, and you want to sent strings of one byte chars. What you need to do is maintain a "reader state", so you can keep track of where you are in reading a message, and not assume it will be everything. It's a extremely crude code sample, but I hope you get my drift.

private enum State
{
   MessageLength
   MessageData
}

private State _state;
private void OnEndReceive(IAsyncCallback ia)
{
    int bytesRead = _socket.EndReceive(ia);


    if (_state == MessageLength) 
    {
        // read and store the message length byte
    }
    else if (_state == State.MessageData)
    {
        // read message data up to the number of bytes received .
        // if there's data left to be read for the current message, read it.
        // if more bytes have been received than there is message data, it means there's a 
        // new message already waiting
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top