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.
/* Method to process recieved 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:
- public class Client
- {
- // State object for receiving data from remote device.
- public class StateObject
- {
- // Client socket.
- public Socket workSocket = null;
- // Size of receive buffer.
- public const int BufferSize = 1024;
- // Receive buffer.
- public byte[] buffer = new byte[1024];
- }
- public static T ByteArrayToStructure
( 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
- {
- // Retrieve the state object and the client socket
- // from the asynchronous state object.
- StateObject state = (StateObject)ar.AsyncState;
- Socket client = state.workSocket;
- // Read data from the remote device.
- int bytesRead = client.EndReceive(ar);
- if (bytesRead > 3)
- {
- //if data does not contain any data to process
- if (data.Length == 0)
- Array.Copy(state.buffer, 0, data, 0, bytesRead);
- else
- {
- //resize data array according to data it contains+data arrived
- Array.Resize(ref data, data.Length + bytesRead);
- //if data array contains data and state.buffer arrives with new data
- Array.Copy(state.buffer, 0, data, data.Length, bytesRead);
- }
- // process all data that exist in data array
- while (data.Length > 2)
- {
- byte[] headerbyte = new byte[2];
- //read two byes of data contains message length in format IPAddress.NetworkToHostOrder
- Array.Copy(data, 0, headerbyte, 0, 2);
- //reverse bytes in headerbyte
- Array.Reverse(headerbyte);
- Array.Copy(headerbyte, 0, data, 1, 1);
- Array.Copy(headerbyte, 1, data, 0, 1);
- //getting recieved message size from structure
- MessageHeader header = ByteArrayToStructure
(data); - int packetSize = header.size;
- //if data contains within data array is partial packet
- if (data.Length < packetSize)
- {
- // Get the rest of the data.
- 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];
- //copy message data to process into message array
- Array.Copy(data, 0, message, 0, packetSize);
- //copy remainng data into a temp array
- Array.Copy(data, packetSize, remainingData, 0, data.Length - packetSize);
- //Method to process recieved packet
- _message.OnRecieve(message);
- //Removing processed Message from data array by resizing it to of size remaingin data and copying content into it
- Array.Resize(ref data, remainingData.Length);
- Array.Copy(remainingData, 0, data, 0, remainingData.Length);
- }
- }
- // Get the rest of the data.
- client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
- new AsyncCallback(ReceiveCallback), state);
- }
- else
- {
- // Create call back for next incoming packet
- client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
- new AsyncCallback(ReceiveCallback), state);
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.ToString());
- }
- }
- }
Replies
Know the answer? Post it — somebody with the same question will find it here.