【问题标题】:Optimizing C# Tcp stream code优化 C# Tcp 流代码
【发布时间】:2013-12-11 15:49:08
【问题描述】:

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

在这种情况下,我有一个“服务器模块”,它创建一个 TcpListener 并接收数据并调用一个函数来发送和接收串行数据。并将其发送回客户端。

所以我目前在我的代码中做了很多转换,现在有一个请求如下。
因为它是一个 modbus 程序,所以我倾向于使用 HEX/Bytes 值来控制所有内容。

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

我想消除其中的一些,我从底部开始。开始不从串行端口上的字节转换为字符串并发送回字节,这样可以节省我的转换和发送三分之一的字节。

我想出了这个代码: 有没有比使用 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 ... }

【问题讨论】:

    标签: c# optimization modbus


    【解决方案1】:

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

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

    下面是如何收集列表中的数据,然后将它们全部放在一个 byte[] 后缀中的示例。我错过了你的一些代码,所以我使用了一个类似的例子作为基础,但适应你的串口代码应该不难。这里的主要部分是包含所有缓冲区以及每个缓冲区使用多少字节的列表。之后,它们都被复制到一个新的 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)
            {
            }
        }
    }
    

    【讨论】:

    • 我需要将它存储在内存中的原因是因为它在某些情况下需要更改,并且将来某个时候存储在数据库中。然而,每个数据接收都需要通过 CRC 校验来验证,并且在发送之前将 crc 添加到字符串中。你能给我一个提示,告诉我如何从这段代码中读取和存储 List 中的所有字节: byte[] TcpReceiveBytes = new byte[TcpClient.ReceiveBufferSize]; int TcpNumBytes = TcpStream.Read(TcpReceiveBytes, 0, TcpClient.ReceiveBufferSize);
    猜你喜欢
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多