在我的C#代码中,我通过TCP链接从DLL接收byte[1024]
。
我为此做的代码我在下面附上。
工作流程
异步数据包在tcp端口收到一个字节数组, 然后将其复制到不同的数组进行处理。
然后根据收到的数据包处理这个复制的数组 大小(每条消息可以是一个接一个的不同大小)。
问题来自于方法,因为到达TCP端口的异步数据随时会被附加到处理缓冲区数组中,在Copy
方法期间它的大小被引用时,多次抛出异常。
在处理一个数据包后,我无法阻止此异步调用。
// Method to process recieved packet
_message.OnRecieve(message);
UI正在更新,并且在用户的操作上再次调用发送和接收方法,其中接收缓冲区数组被新数据覆盖。
分享一段代码:
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<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
{
// 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<MessageHeader>(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());
}
}
}