Нужна критика и совет по оптимизации работы класса на сокетах - C#

Узнай цену своей работы

Формулировка задачи:

Написал класс для работы с устройствами по протоколу Modbus TCP. Читаю регистры (один регистр это два байта) 9999 регистров моя программа читает более секунды, это не учитывая, что полученный результат нужно складывать в массив отдельный. По сути же, она должна в пару десятков миллисекунд отрабатывать. Program.cs
static void Main(string[] args)
        {
            try
            {
                ModbusTCP device = new ModbusTCP();
                device.Connect(502, 1, "192.168.1.21", 1, true, 1000);
 
                ushort[] registers = new ushort[9999];
 
                DateTime start = DateTime.Now;
                for (int i = 0; i < 80; i++)
                {
                    device.ReadUsignedHoldingRegisters((ushort)(40001 + i * 125), 125);
                }
                DateTime finish = DateTime.Now;
 
                Console.WriteLine(finish - start);
                Console.ReadKey();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
ModbusTCP.cs
public class ModbusTCP
    {
        private int port;
        private byte modbusStation;
        private string ipAddress;
        private ushort shift;    //отсчет регистров с 0 или с 1
        private bool byteOrder;  //порядок байт
 
        public Socket Socket { get; set; }
 
        public ModbusTCP() { }
 
        public void Connect(int _port, byte _modbusStation, string _ipAddress, ushort _shift, bool _byteOrder, int timeout)
        {
            try
            {
                port = _port;
                modbusStation = _modbusStation;
                shift = _shift;
                byteOrder = _byteOrder;
                ipAddress = _ipAddress;
                IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
                Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                Socket.ReceiveTimeout = timeout;
                Socket.Connect(ipPoint);
            }
            catch
            {
                
            }
        }
 
        public ushort[] ReadUsignedHoldingRegisters(ushort firstRegister, ushort amountRegisters)
        {
            if (firstRegister >= 40000 && firstRegister < 50000) firstRegister -= 40000;
            byte[] dataReceive = SendReceive(CreateDataForReadHoldingRegisters(firstRegister, amountRegisters));
            ushort[] dataUshort = new ushort[amountRegisters];
            for (int i = 0; i < amountRegisters; i++)
            {
                byte[] byteTemp = new byte[2];
                if (byteOrder) byteTemp = new byte[2] { dataReceive[i * 2 + 10], dataReceive[i * 2 + 9] };
                else byteTemp = new byte[2] { dataReceive[i * 2 + 9], dataReceive[i * 2 + 10] };
                dataUshort[i] = BitConverter.ToUInt16(byteTemp, 0);
            }
            return dataUshort;
        }
 
        private List<byte[]> CreateDataForReadHoldingRegisters(ushort firstRegister, ushort amountRegisters)
        {
            byte[] dataSend = new byte[12]; //запрос на чтение
 
            byte[] dataReceive = new byte[9 + amountRegisters * 2]; //ответ от устройства
            firstRegister -= shift; //адресс первого регистра в соответствии со сдвигом
 
            //Формирую запрос
 
            //идентификатор транзакции
            dataSend[0] = 30;
            dataSend[1] = 0;
            //идентификатор протокола
            dataSend[2] = 0;
            dataSend[3] = 0;
            //длина сообщения
            dataSend[4] = 0;
            dataSend[5] = 6;
            //адрес устройства
            dataSend[6] = modbusStation;
            //функция
            dataSend[7] = 3;
            //адрес первого регистра
            dataSend[8] = BitConverter.GetBytes(firstRegister)[1];
            dataSend[9] = BitConverter.GetBytes(firstRegister)[0];
            //количество необходимых регистров
            dataSend[10] = BitConverter.GetBytes(amountRegisters)[1];
            dataSend[11] = BitConverter.GetBytes(amountRegisters)[0];
 
            return new List<byte[]>() { dataSend, dataReceive };
        }
 
        private byte[] SendReceive(List<byte[]> data)
        {
            Socket.Send(data[0]);
            Socket.Receive(data[1]);
            return data[1];
        }

Решение задачи: «Нужна критика и совет по оптимизации работы класса на сокетах»

textual
Листинг программы
        public void Read(ushort firstRegister, ushort amountRegisters)
        {
            if (firstRegister >= 40000 && firstRegister < 50000) firstRegister -= 40000;
            byte[] dataSend = new byte[12]; //запрос на чтение
 
            byte[] dataReceive = new byte[9 + amountRegisters * 2]; //ответ от устройства
            firstRegister -= shift; //адресс первого регистра в соответствии со сдвигом
 
            //Формирую запрос
            identifierTranzaction++;
            //идентификатор транзакции
            dataSend[0] = BitConverter.GetBytes(identifierTranzaction)[1];
            dataSend[1] = BitConverter.GetBytes(identifierTranzaction)[0];
            //идентификатор протокола
            dataSend[2] = 0;
            dataSend[3] = 0;
            //длина сообщения
            dataSend[4] = 0;
            dataSend[5] = 6;
            //адрес устройства
            dataSend[6] = modbusStation;
            //функция
            dataSend[7] = 3;
            //адрес первого регистра
            dataSend[8] = BitConverter.GetBytes(firstRegister)[1];
            dataSend[9] = BitConverter.GetBytes(firstRegister)[0];
            //количество необходимых регистров
            dataSend[10] = BitConverter.GetBytes(amountRegisters)[1];
            dataSend[11] = BitConverter.GetBytes(amountRegisters)[0];
 
            Socket.Send(dataSend);
            Socket.Receive(dataReceive);
 
            ushort[] dataUshort = new ushort[amountRegisters];
            for (int i = 0; i < amountRegisters; i++)
            {
                byte[] byteTemp = new byte[2] { dataReceive[i * 2 + (byteOrder ? 10 : 9)], dataReceive[i * 2 + (byteOrder ? 9 : 10)] };
                dataUshort[i] = BitConverter.ToUInt16(byteTemp, 0);
            }
 
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 4.071 из 5
Похожие ответы