IPManager.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using System.Net;
  6. using WingServerCommon.Utilities;
  7. namespace WingServerCommon.Interfaces.Cache
  8. {
  9. /// <summary>
  10. /// IP 管理接口
  11. /// </summary>
  12. public interface IIPManager : IBaseCacheManager<CacheIPInfoDTO>
  13. {
  14. /// <summary>
  15. /// 根据IP获取内存中对应IP段的详细信息
  16. /// </summary>
  17. /// <param name="ip">ip</param>
  18. /// <returns>IP段的详细信息</returns>
  19. public CacheIPInfoDTO GetIPInfo(string ip);
  20. /// <summary>
  21. /// 加载IP段文件
  22. /// </summary>
  23. /// <param name="path">文件路径</param>
  24. public void LoadData(string path);
  25. }
  26. /// <summary>
  27. /// IP 管理类
  28. /// </summary>
  29. public class IPManager : CacheManager<CacheIPInfoDTO>, IIPManager
  30. {
  31. private List<CacheIPInfoDTO> _ipList = new List<CacheIPInfoDTO>();
  32. private StartRangeComparer startRangeComparer = new StartRangeComparer();
  33. /// <summary>
  34. /// 根据IP获取内存中对应IP段的详细信息
  35. /// </summary>
  36. /// <param name="ip"></param>
  37. /// <returns></returns>
  38. public CacheIPInfoDTO GetIPInfo(string ip)
  39. {
  40. using (new Performance(5, "{0} GetIPInfo {1}", $"{this.GetType().Name}",$"{ip}"))
  41. {
  42. var longIP = IpToLong(ip);
  43. var index = _ipList.BinarySearch(new CacheIPInfoDTO { LongStartIP = longIP }, startRangeComparer);
  44. int candidateIndex = index >= 0 ? index : (~index) - 1;
  45. if (candidateIndex < 0)
  46. {
  47. return null;
  48. }
  49. CacheIPInfoDTO candidate = _ipList[candidateIndex];
  50. if (candidate.LongEndIP >= longIP)
  51. {
  52. return candidate;
  53. }
  54. else
  55. {
  56. return null;
  57. };
  58. }
  59. }
  60. /// <summary>
  61. /// 加载IP段文件
  62. /// </summary>
  63. /// <param name="path">文件路径</param>
  64. public void LoadData(string path)
  65. {
  66. List<CacheIPInfoDTO> list = new List<CacheIPInfoDTO>();
  67. DirectoryInfo dirInfo = new DirectoryInfo(path);
  68. if (dirInfo != null)
  69. {
  70. FileInfo[] fileInfos = dirInfo.GetFiles();
  71. if (fileInfos != null && fileInfos.Length > 0)
  72. {
  73. foreach (var fileInfo in fileInfos)
  74. {
  75. using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, FileShare.ReadWrite))
  76. {
  77. using (StreamReader sr = new StreamReader(fs, System.Text.Encoding.UTF8))
  78. {
  79. var json = sr.ReadToEnd();
  80. if (!string.IsNullOrEmpty(json))
  81. {
  82. var contentList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CacheIPInfoDTO>>(json);
  83. if (contentList != null && contentList.Count > 0)
  84. {
  85. list.AddRange(contentList);
  86. }
  87. }
  88. }
  89. }
  90. }
  91. }
  92. }
  93. _ipList = list.OrderBy(v => v.LongStartIP).ToList();
  94. }
  95. /// <summary>
  96. /// ip to long
  97. /// </summary>
  98. /// <param name="ip"></param>
  99. /// <returns></returns>
  100. private long IpToLong(string ip)
  101. {
  102. byte[] byts = IPAddress.Parse(ip).GetAddressBytes();
  103. Array.Reverse(byts); // 需要倒置一次字节序
  104. long ipLong = BitConverter.ToUInt32(byts, 0);
  105. return ipLong;
  106. }
  107. }
  108. public class StartRangeComparer : IComparer<CacheIPInfoDTO>
  109. {
  110. public int Compare(CacheIPInfoDTO first, CacheIPInfoDTO second)
  111. {
  112. return first.LongStartIP.CompareTo(second.LongStartIP);
  113. }
  114. }
  115. /// <summary>
  116. /// IP 信息对象类
  117. /// </summary>
  118. public class CacheIPInfoDTO : ICacheObject
  119. {
  120. /// <summary>
  121. /// 起始 long 类型IP
  122. /// </summary>
  123. /// <value></value>
  124. public long LongStartIP { get; set; }
  125. /// <summary>
  126. /// 结束 long 类型IP
  127. /// </summary>
  128. /// <value></value>
  129. public long LongEndIP { get; set; }
  130. /// <summary>
  131. ///纬度
  132. /// </summary>
  133. /// <value></value>
  134. public double Lat { get; set; }
  135. /// <summary>
  136. /// 经度
  137. /// </summary>
  138. /// <value></value>
  139. public double Lng { get; set; }
  140. /// <summary>
  141. /// 国家
  142. /// </summary>
  143. /// <value></value>
  144. public string Country { get; set; }
  145. /// <summary>
  146. ///
  147. /// </summary>
  148. /// <value></value>
  149. public string Province { get; set; }
  150. /// <summary>
  151. ///城市
  152. /// </summary>
  153. /// <value></value>
  154. public string City { get; set; }
  155. /// <summary>
  156. ///区县
  157. /// </summary>
  158. /// <value></value>
  159. public string Districts { get; set; }
  160. /// <summary>
  161. ///是否中国大陆境内或者境外
  162. /// </summary>
  163. /// <value></value>
  164. public bool IsChinaMainland { get; set; }
  165. /// <summary>
  166. ///
  167. /// </summary>
  168. /// <value></value>
  169. public string Code { get; set; }
  170. }
  171. }