Нужна критика и совет по оптимизации работы класса на сокетах - 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);
}
}