I need to receive an async message.
In all messages, first 2 byte indicate the length of next byte array. My problem is that in few case I receive unexpected packets.
If I use Thread.Sleep(200)
this problems does't happen, or happens rarely.
Where am I wrong?
protected void StartListening()
{
StateObject state = new StateObject() { ProcessHeader = true };
state.PrepareBuffer(HeaderLength);
lock (_secureConnection)
_secureConnection.BeginReceive(state.Buffer, 0, HeaderLength, 0, new AsyncCallback(ReadCallback), state);
}
private void ReadCallback(IAsyncResult ar)
{
if (_disposing)
return;
StateObject state = (StateObject)ar.AsyncState;
try
{
lock (_secureConnection)
_secureConnection.EndReceive(ar);
if (state.ProcessHeader)
{
state.ProcessHeader = !state.ProcessHeader;
var bodyLength = GetBodyLength(state.Buffer);
//Thread.Sleep(200);
state.CompleteMessage.AddRange(state.Buffer);
state.PrepareBuffer(bodyLength);
lock (_secureConnection)
_secureConnection.BeginReceive(state.Buffer, 0, bodyLength, 0, new AsyncCallback(ReadCallback), state);
}
else
{
state.CompleteMessage.AddRange(state.Buffer);
ProcessMessage(state.CompleteMessage); //process this message
//Thread.Sleep(200);
state.ProcessHeader = !state.ProcessHeader;
state.CompleteMessage.Clear();
state.PrepareBuffer(HeaderLength);
lock (_secureConnection)
_secureConnection.BeginReceive(state.Buffer, 0, HeaderLength, 0, new AsyncCallback(ReadCallback), state);
}
}
catch (Exception e)
{
Close(true);
}
}
class StateObject
{
public StateObject()
{
ProcessHeader = true;
}
public byte[] Buffer { get; private set; }
public bool ProcessHeader { get; set; }
public List<byte> CompleteMessage = new List<byte>();
public void PrepareBuffer(int size)
{
Buffer = new byte[size];
}
}
You are assuming that TCP is a message-based protocol. It is a stream of bytes, though. Your reads can read any amount greater than zero. This is just like with a FileStream. Files do not have messages, either.
Your code has to deal with that fact. Search for "TCP message framing".