In my C# code I am receiving a byte[1024] from a DLL through TCP link. Code I did for this I am attaching below.
The workflow is
An asynchronous packet gets received at tcp port into a byte array, which then gets copied to a different array for processing.
This copied array then gets processed according to received packet size(each message could be of different size one behind another).
While in the meantime async method received another data which should get appended to array used for processing packet.
Problem coming is being method as asynchronous data arriving at TCP port is getting appended anytime to the processing buffer array which many times throws exceptions while its size is getting referred during Copy methods. I am unable to block this async call as after processing one packet.
_message.OnRecieve(message);
UI is getting updated and on user's action again the send and receive methods getting called where receive buffer array gets overwritten with new data.
Sharing piece of code:
What I have tried:
public class Client
{
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[1024];
}
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
}
[StructLayout(LayoutKind.Sequential,Pack = 2)]
public struct MessageHeader
{
public int size;
}
private static byte[] data = new byte[1024 * 10];
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 3)
{
if (data.Length == 0)
Array.Copy(state.buffer, 0, data, 0, bytesRead);
else
{
Array.Resize(ref data, data.Length + bytesRead);
Array.Copy(state.buffer, 0, data, data.Length, bytesRead);
}
while (data.Length > 2)
{
byte[] headerbyte = new byte[2];
Array.Copy(data, 0, headerbyte, 0, 2);
Array.Reverse(headerbyte);
Array.Copy(headerbyte, 0, data, 1, 1);
Array.Copy(headerbyte, 1, data, 0, 1);
MessageHeader header = ByteArrayToStructure<MessageHeader>(data);
int packetSize = header.size;
if (data.Length < packetSize)
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
byte[] message = new byte[packetSize];
byte[] remainingData = new byte[data.Length - packetSize];
Array.Copy(data, 0, message, 0, packetSize);
Array.Copy(data, packetSize, remainingData, 0, data.Length - packetSize);
_message.OnRecieve(message);
Array.Resize(ref data, remainingData.Length);
Array.Copy(remainingData, 0, data, 0, remainingData.Length);
}
}
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}