无法创建动态字节[]来处理通过异步TCP套接字响应接收的数据 [英] Unable to create a dynamic byte[] to process data received through async TCP socket response
问题描述
在我的C#代码中,我通过TCP链接从DLL接收一个字节[1024]。我为此做的代码我在下面附上。
工作流程是
收到异步数据包在tcp端口进入一个字节数组,然后将其复制到另一个数组进行处理。
然后根据收到的数据包大小处理这个复制的数组(每个消息都可以一个接一个地大小不同。
同时异步方法接收到另一个数据应该附加到用于处理数据包的数组。
问题来源是方法,因为到达TCP端口的异步数据随时被附加到处理缓冲区数组,在复制方法期间它的大小被引用时多次抛出异常。在处理一个数据包后,我无法阻止此异步调用。
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正在更新,并且再次根据用户的操作调用发送和接收方法,其中接收缓冲区数组被新数据覆盖。
分享一段代码:
我尝试过:
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
{
// 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());
}
}
}
推荐答案
您(有效地)使用静态数据缓冲区你的输入消息,所以任何时候一些数据到达它有可能破坏已经存在的东西。您应该在异步事件处理程序中分配缓冲区,捕获数据,并将缓冲区传递给将处理它的方法。然后,如果有更多数据到达,您将创建一个新缓冲区,而不是覆盖仍在处理的内容。
您的代码中还有以下行:
You are (effectively) using a static data buffer for your input messages, so any time some data arrives it has the potential to destroy what is already there. You should allocate your buffer in the async event handler, capture the data, and pass the buffer off to the method that will process it. Then if more data arrives you will create a new buffer rather than overwriting what is still being processed.
Also you have the following line in your code:
public const int BufferSize = 1024;
但您仍然在任何地方使用硬编码值 1024
。您应该使用常量名称,例如:
but you still use th hard coded value 1024
everywhere. You should use the constant name like:
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
因此,如果您从1024更改,则无需在代码中搜索使用该数字的其他地方。
So if you ever change from 1024, you will not need to search the code for other places where that number is used.
这篇关于无法创建动态字节[]来处理通过异步TCP套接字响应接收的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!