HeartBeatUdpProxy.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. using Edge.Core.Parser.BinaryParser.Util;
  2. using Microsoft.Extensions.Logging;
  3. using Microsoft.Extensions.Logging.Abstractions;
  4. using PetroChinaOnlineWatchPlugin.MessageEntity.Outgoing;
  5. using System;
  6. using System.Diagnostics;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. namespace PetroChinaOnlineWatchPlugin
  10. {
  11. internal class HeartBeatUdpProxy
  12. {
  13. public event EventHandler OnDataReceived;
  14. public static HeartBeatUdpProxy Default => instance;
  15. private static readonly HeartBeatUdpProxy instance = new HeartBeatUdpProxy();
  16. private int heartBeatUdpPortNumber = 0;
  17. private UdpClient heartBeatUdpClient;
  18. private ILogger logger = NullLogger.Instance;
  19. private string localIpAddresses = string.Empty;
  20. private string broadcastIpAddresses = string.Empty;
  21. private AppConfigV1 appConfig;
  22. public bool Start(AppConfigV1 appConfig, ILogger logger)
  23. {
  24. this.appConfig = appConfig;
  25. this.logger = logger;
  26. heartBeatUdpPortNumber = appConfig.HeartBeatPortNumber;
  27. // setup heartBeat UdpClient
  28. heartBeatUdpClient = new UdpClient(new IPEndPoint(IPAddress.Any, heartBeatUdpPortNumber))
  29. { EnableBroadcast = true };
  30. heartBeatUdpClient.BeginReceive(Udp_DataReceived, null);
  31. GetLocalIp();
  32. return true;
  33. }
  34. public void Udp_SendData()
  35. {
  36. try
  37. {
  38. var outHeartBeat = new HeartBeatOut()
  39. {
  40. IpAddress = localIpAddresses,
  41. Port = ConnectionController.Default.TcpListenPort,
  42. Subnet = appConfig.LocalSubnet,
  43. Node = appConfig.LocalNode
  44. };
  45. byte[] heartBeatRawDataToSend = Parser.Default.Serialize(outHeartBeat);
  46. logger.LogTrace($"Udp Outgoing--->: 0x{heartBeatRawDataToSend.ToHexLogString()}");
  47. heartBeatUdpClient.Send(heartBeatRawDataToSend, heartBeatRawDataToSend.Length,
  48. broadcastIpAddresses, heartBeatUdpPortNumber);
  49. }
  50. catch (Exception ex)
  51. {
  52. logger.LogError($"Exception in Udp_SendData(...):\r\n{ex}");
  53. }
  54. }
  55. private void Udp_DataReceived(IAsyncResult ar)
  56. {
  57. try
  58. {
  59. // IFSF always have 10 bytes heartbeat: ip0.ip1.ip2,ip3,port(2 bytes),4 ifsf standard bytes
  60. var broadcastHeartBeatReceiveEP = new IPEndPoint(IPAddress.Any, 0);
  61. byte[] heartBeatBytes = heartBeatUdpClient.EndReceive(ar, ref broadcastHeartBeatReceiveEP);
  62. logger.LogTrace($"Udp Incoming--->: 0x{heartBeatBytes.ToHexLogString()}");
  63. dynamic heartBeat = Parser.Default.Deserialize(heartBeatBytes);
  64. logger.LogTrace($"HeartBeatIncoming--->: {heartBeat.ToString()}");
  65. if (heartBeat.Subnet == appConfig.RemoteSubnet && heartBeat.Node == appConfig.RemoteNode)
  66. {
  67. logger.LogTrace($"Received heart beat from IpAddress:Port, {heartBeat.ToString()}");
  68. if (!ConnectionController.Default.TcpClientInstance.Connected)
  69. OnDataReceived?.Invoke(this, new UdpDataEventArgs() { IpAddress = heartBeat.IpAddress, Port = heartBeat.Port });
  70. }
  71. }
  72. catch (Exception ex)
  73. {
  74. logger.LogError($"Exception in Udp_DataReceived(...):\r\n{ex}");
  75. }
  76. finally
  77. {
  78. heartBeatUdpClient.BeginReceive(Udp_DataReceived, null);
  79. }
  80. }
  81. private void GetLocalIp()
  82. {
  83. try
  84. {
  85. //var localIpAddresses = NetworkInterface.GetAllNetworkInterfaces()
  86. // .Where(i => i.SupportsMulticast && i.Supports(NetworkInterfaceComponent.IPv4))
  87. // .SelectMany(i => i.GetIPProperties().UnicastAddresses)
  88. // .Select(ad => ad.Address)
  89. // .Where(ad => ad.AddressFamily == AddressFamily.InterNetwork);
  90. //logger.LogInformation("Local ip addresses are: " + localIpAddresses.Select(i => i.ToString())
  91. // .Aggregate((acc, n) => acc + ", " + n));
  92. var cmd = new Process();
  93. cmd.StartInfo.FileName = "ipconfig.exe";
  94. cmd.StartInfo.RedirectStandardOutput = true;
  95. cmd.StartInfo.RedirectStandardInput = true;
  96. cmd.StartInfo.UseShellExecute = false;
  97. cmd.StartInfo.CreateNoWindow = true;
  98. cmd.Start();
  99. string info = cmd.StandardOutput.ReadToEnd();
  100. cmd.WaitForExit();
  101. cmd.Close();
  102. info = info.Substring(info.IndexOf(appConfig.NetworkConnections));
  103. string ipFlag = "IPv4 Address. . . . . . . . . . . : ";
  104. int index = info.IndexOf(ipFlag);
  105. if (index > 0)
  106. {
  107. info = info?.Substring(index + ipFlag.Length);
  108. }
  109. else
  110. {
  111. ipFlag = "IPv4 地址 . . . . . . . . . . . . : ";
  112. info = info?.Substring(info.IndexOf(ipFlag) + ipFlag.Length);
  113. }
  114. localIpAddresses = info?.Split("\r\n")[0];
  115. logger.LogInformation($"Local ip addresses is: {localIpAddresses}");
  116. ipFlag = "Subnet Mask . . . . . . . . . . . : ";
  117. index = info.IndexOf(ipFlag);
  118. if (index > 0)
  119. {
  120. info = info?.Substring(index + ipFlag.Length);
  121. }
  122. else
  123. {
  124. ipFlag = "子网掩码 . . . . . . . . . . . . : ";
  125. info = info?.Substring(info.IndexOf(ipFlag) + ipFlag.Length);
  126. }
  127. string subnetMask = info?.Split("\r\n")[0];
  128. logger.LogInformation($"Local subnet mask is: {subnetMask}");
  129. broadcastIpAddresses = GetBroadcastIpAddresses(localIpAddresses, subnetMask);
  130. logger.LogInformation($"Broadcast ip addresses is: {broadcastIpAddresses}");
  131. }
  132. catch (Exception ex)
  133. {
  134. logger.LogError($"Exception in GetLocalIp(...):\r\n{ex}");
  135. }
  136. }
  137. private string GetBroadcastIpAddresses(string ipAddress, string subnetMask)
  138. {
  139. byte[] ipBuffer = IpAddress2Bytes(ipAddress);
  140. byte[] smBuffer = IpAddress2Bytes(subnetMask);
  141. return $"{ipBuffer[0] | Negate(smBuffer[0])}.{ipBuffer[1] | Negate(smBuffer[1])}." +
  142. $"{ipBuffer[2] | Negate(smBuffer[2])}.{ipBuffer[3] | Negate(smBuffer[3])}";
  143. }
  144. private byte Negate(byte value)
  145. {
  146. int first = value >> 7;
  147. if (first == 1)
  148. {
  149. value = (byte)(value & 0x7F);
  150. value = (byte)(~value & 0x7F);
  151. }
  152. else
  153. {
  154. value = (byte)(~value);
  155. }
  156. return value;
  157. }
  158. private byte[] IpAddress2Bytes(string ipAddress)
  159. {
  160. byte[] buffer = new byte[4];
  161. int i = 0;
  162. foreach (string item in ipAddress.Split('.'))
  163. {
  164. buffer[i++] = byte.Parse(item);
  165. }
  166. return buffer;
  167. }
  168. }
  169. public class UdpDataEventArgs : EventArgs
  170. {
  171. public string IpAddress { get; set; }
  172. public int Port { get; set; }
  173. }
  174. }