无法创建动态字节[]来处理通过异步TCP套接字响应接收的数据 [英] Unable to create a dynamic byte[] to process data received through async TCP socket response

查看:58
本文介绍了无法创建动态字节[]来处理通过异步TCP套接字响应接收的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆