Визуальная электроника

Кроме работы по интерфейсу RS485, наш газоанализатор может работать по интерфейсу ETHERNET с протоколом UDP. UDP (User Datagram Protocol) представляет сетевой протокол, который позволяет доставить данные на удаленный узел. Для этого передачи сообщений по протоколу UDP нет надобности использовать сервер, данные напрямую передаются от одного узла к другому. Снижаются накладные расходы при передаче, по сравнению с TCP, сами данные передаются быстрее. Все посылаемые сообщения по протоколу UDP называются дейтаграммами. Также через UDP можно передавать широковещательные сообщения для для набора адресов в подсети. В этой статье мы создадим class ETHServer для общения по интерфейсу ETHERNET с помощью UDP пакетов. Начиная с фреймворка .Net 1.1 (и более поздних версий .NET) компания Microsoft добавила поддержку UDP соединения, включением класса UdpClient как части пространства имен System.Net.Sockets. Для начала опишем используемые классом переменные:

C# Code:
  1. UdpClient sender;
  2. IPEndPoint endPoint;
  3. UdpClient receivingUdpClient;
  4. IPEndPoint RemoteIpEndPoint;
  5. // Статус клиента
  6. private bool client_running;
  7. private IPAddress rIPAddress;
  8. private int rPort;
  9. private int lPort;
  10. private int loc_req;
  11. // Поток
  12. Thread th;

На следующем этапе реализуем функцию Connect, отвечающую за открытие нашего UDP соединения:

C# Code:
  1. public void Connect(IPAddress remoteIPAddress, int remotePort, int localPort)
  2. {
  3. try
  4. {
  5. // Создаем UdpClient
  6. lPort = localPort;
  7. rPort = remotePort;
  8. rIPAddress = remoteIPAddress;
  9. th = new Thread(new ThreadStart(Receiver));
  10. th.Start();
  11. client_running = true;
  12. }
  13. catch (Exception ex)
  14. {
  15. Console.WriteLine("ERROR: " + ex.ToString() + "MESSAGE " + ex.Message);
  16. }
  17. }

Как видите функция получилась достаточно простой. В качестве аргументов она принимает IP адрес к которому мы хотим подключиться, удаленный и локальный порты. В нашем примере газоанализатор выступает в роли классического сервера. Наше приложение подключается к устройству, посылает запросы, и слушает ответы.

Для приема данных нам нужно создать функцию Receiver, как вы заметили, именно она выступает в качестве функции вызываемой в потоке (Thread):

C# Code:
  1. public void Receiver()
  2. {
  3. // Создаем endPoint по информации об удаленном хосте
  4. endPoint = new IPEndPoint(rIPAddress, rPort);
  5. // Создаем UdpClient для чтения входящих данных
  6. receivingUdpClient = new UdpClient(lPort);
  7. RemoteIpEndPoint = null;
  8.  
  9. try
  10. {
  11. Console.WriteLine("Поток чтения стартовал\n");
  12.  
  13. while (client_running)
  14. {
  15. // Ожидание дейтаграммы
  16. Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
  17.  
  18. // Преобразуем и отображаем данные
  19. string returnData = Encoding.UTF8.GetString(receiveBytes);
  20. Console.WriteLine("ETHER --> " + returnData.ToString());
  21.  
  22. if (loc_req == 1)//GET Device
  23. {
  24. Ans_Device newDevice = JsonConvert.DeserializeObject(returnData);
  25. Form1.myForm.Device1.DrawDeviceData(newDevice);
  26. newDevice = null;
  27. }
  28. }
  29. }
  30. catch (Exception ex)
  31. {
  32. Console.WriteLine("ERROR: " + ex.ToString() + "MESSAGE " + ex.Message);
  33. }
  34. }

Мы уже писали про использование формата JSON для общения наших устройств с серверным ПО. По этому в потоке происходит чтение данных с нашего UDP клиента, и далее для десериализации принятых данных используется компонент JsonConvert Class. Использовать его достаточно просто, для парсинга принятых данных, необходимо создать класс, соответствующий нашему запросу:

C# Code:
  1. //Класс ответа девайса
  2. public class Ans_Device
  3. {
  4. public string ANSWER { get; set; }
  5. public string NAME { get; set; }
  6. public int SENSORS { get; set; }
  7. public byte RS485_ADRESS { get; set; }
  8. public int[] IP_ADDRESS { get; set; }
  9. public int[] NETMASK { get; set; }
  10. public int[] GATEWAY { get; set; }
  11. }

Для десеарилизации наших данных достаточно создать экземпляр класса Ans_Device с нашими десериализованными данными:

C# Code:
  1. Ans_Device newDevice = JsonConvert.DeserializeObject(returnData);

Для завершения создания нашего класса осталось реализовать два простых метода. Первый, это метод Send, отправляющий данные в UDP сокет:

C# Code:
  1. public void Send(string datagram, int request)
  2. {
  3. sender = new UdpClient();
  4.  
  5. loc_req = request;
  6. try
  7. {
  8. // Преобразуем данные в массив байтов
  9. byte[] bytes = Encoding.UTF8.GetBytes(datagram);
  10.  
  11. // Отправляем данные
  12. Console.WriteLine("ETHER <-- " + datagram.ToString());
  13. sender.Send(bytes, bytes.Length, endPoint);
  14. }
  15. catch (Exception ex)
  16. {
  17. Console.WriteLine("ERROR: " + ex.ToString() + "MESSAGE " + ex.Message);
  18. }
  19. finally
  20. {
  21. // Закрыть соединение
  22. sender.Close();
  23. }
  24. }

Второй, это метод Close, закрывающий наше соединение, и остановка нашего потока:

C# Code:
  1. public void DisConnect()
  2. {
  3. try
  4. {
  5. client_running = false;
  6. th.Abort();
  7. th.Join(500);
  8. receivingUdpClient.Close();
  9. th = null;
  10. }
  11. catch (Exception ex)
  12. {
  13. Console.WriteLine("ERROR: " + ex.ToString() + "MESSAGE " + ex.Message);
  14. }
  15. }

Ниже можно наблюдать видео работы получившегося класса.

Добавить комментарий