Нужна критика и совет по оптимизации работы класса на сокетах - 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); } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д