Нужна критика и совет по оптимизации работы класса на сокетах - C#
Формулировка задачи:
Написал класс для работы с устройствами по протоколу Modbus TCP. Читаю регистры (один регистр это два байта) 9999 регистров моя программа читает более секунды, это не учитывая, что полученный результат нужно складывать в массив отдельный. По сути же, она должна в пару десятков миллисекунд отрабатывать.
Program.cs
ModbusTCP.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());
- }
Листинг программы
- 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);
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д