优化C#Tcp流代码

时间:2013-12-11 15:49:09

标签: c# optimization modbus

我目前正在尝试优化我用于与串口通信并在其他设备上显示的程序的代码。

在该上下文中,我有一个“服务器模块”,它创建一个TcpListener并接收数据并调用一个函数来发送和接收串行数据。并将其发回给客户。

所以我目前在我的代码中进行了大量的转换,请求在当下如下 因为它是一个modbus程序,我倾向于用HEX / Bytes值来做我所有的东西来控制什么。

因此我确实在字节和字符串之间进行了很多转换。

我想消除其中的一些,我从buttom开始。开始不要从串口的字节转换为字符串,只返回字节,这样就可以节省转换次数和发送的三分之一字节。

我想出了这段代码: 有没有比使用Array.Resize更聪明的方法,我尝试使用List但我不能让它正常工作它保持空白。

    while (TcpService_Listen)
    {
        if (TcpListener.Pending())
        {
            try
            {
                TcpClient TcpClient = TcpListener.AcceptTcpClient();
                NetworkStream TcpStream = TcpClient.GetStream();

                if (TcpStream.CanRead)
                {

                    //List<byte> list = new List<byte>(4096);
                    //Console.Write(list.Count);

                    byte[] TcpReceiveBytes = new byte[TcpClient.ReceiveBufferSize];
                    int TcpNumBytes = TcpStream.Read(TcpReceiveBytes, 0, TcpClient.ReceiveBufferSize);
                    Array.Resize(ref TcpReceiveBytes, TcpNumBytes);

                    Console.WriteLine("TcpReceiveBytes: " + BitConverter.ToString(TcpReceiveBytes));

                    byte[] TcpResponseBytes = new byte[0];
                    SendReceive(TcpReceiveBytes, ref TcpResponseBytes);
                    TcpStream.Write(TcpResponseBytes, 0, TcpResponseBytes.Length);

                    Console.WriteLine("TcpResponseBytes: " + BitConverter.ToString(TcpResponseBytes));
                }

                TcpStream.Close();
                TcpClient.Close();

            }
            catch (Exception ex)
            {
                Console.Write("ERROR:TCPDATA:" + ex.Message);
            }
        }
    }
private static void SendReceive(byte[] byteRequest, ref byte[] byteResponse) 
{ //blabla send and receive stuff on serialPort ... }

1 个答案:

答案 0 :(得分:1)

优化此类逻辑的最佳方法是不将所有内容存储在内存中,而是在收到数据后尽快删除数据块。我不清楚为什么你需要将所有内容存储在内存中,但如果你不这样做,只需将其发送到另一个串行设备,或文件或网络通道。

如果您仍然需要在发送之前接收所有内容,例如,如果它是一个xml文件,您需要在将其存储到磁盘之前进行更改和验证,您可以将这些块存储在List中,直到您拥有所有内容。然后你可以创建一个新的byte []并将所有内容复制到那里。经验法则是,更少的内存分配将提高性能。

下面是一个如何收集列表中的数据然后将其全部放在一个byte []后面的示例。我错过了你的一些代码,所以我使用了类似的例子作为基础,但它不应该很难适应你的串口代码。这里的主要部分是List,它包含所有缓冲区以及每个缓冲区使用的字节数。然后将它们全部复制到一个新的byte []中,该byte []具有容纳所有字节的空间。 我没有机会测试正在运行的代码,所以在投入生产之前要进行一些测试。

class Program
{
    class Chunk
    {
        public int Size { get; set; }
        public byte[] Data { get; set; }
    }

    static void Main(string[] args)
    {

        try
        {
            int buffersize = 1024;
            TcpListener server = new TcpListener(IPAddress.Any, 13000);
            server.Start();

            var chunks = new List<Chunk>();
            while (true)
            {
                byte[] bytes = new byte[buffersize];

                TcpClient client = server.AcceptTcpClient();
                NetworkStream stream = client.GetStream();
                int i;
                i = stream.Read(bytes, 0, bytes.Length);
                chunks.Add(new Chunk{Size = i, Data = bytes});
                while (i != 0)
                {
                    byte[] leBytes = new byte[buffersize];
                    i = stream.Read(leBytes, 0, leBytes.Length);
                    chunks.Add(new Chunk{Size = i, Data = bytes});
                }
                client.Close();

                int totalSize = chunks.Select(x => x.Size).Sum();
                var allData = new byte[totalSize];
                int offset = 0;
                foreach(var chunk in chunks)
                {
                    Buffer.BlockCopy(chunk.Data,0,allData,offset,chunk.Size);
                    offset += chunk.Size;
                }
            }
        }
        catch (SocketException e)
        {
        }
    }
}