C# 读取纯真IP数据库显示IP地理位置

[ 33391 查看 / 176 回复 ]

读大学时写的代码,不够优雅,凑合能用,现共享出来方便有此需求的朋友。
首先要下载纯真IP数据库,然后在代码中指定数据库文件的路径,传入一个IP即可返回其地理位置,请参考Main函数。
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.IO;
  5. namespace 纯真IP数据库研究
  6. {
  7.     ///<summary>
  8.     /// 提供从纯真IP数据库搜索IP信息的方法;
  9.     ///</summary>
  10.     public class IPSearch
  11.     {
  12.         FileStream ipFile;
  13.         long ip;
  14.         string ipfilePath;

  15.         ///<summary>
  16.         /// 构造函数
  17.         ///</summary>
  18.         ///<param name="ipfilePath">纯真IP数据库路径</param>
  19.         public IPSearch(string ipfilePath)
  20.         {
  21.             this.ipfilePath = ipfilePath;
  22.         }
  23.         //测试
  24.         static void Main(string[] args)
  25.         {
  26.             string ipfilePath = @"C:\Documents and Settings\Daode\桌面\qqwry\QQWry.dat";
  27.             IPSearch ipSearch = new IPSearch(ipfilePath);
  28.             string ip = "72.51.27.51";
  29.             IPSearch.IPLocation loc = ipSearch.GetIPLocation(ip);
  30.             Console.WriteLine("你查的ip是:{0} 地理位置:{1} {2}", ip, loc.country, loc.area);
  31.             Console.ReadKey();
  32.         }
  33.         ///<summary>
  34.         /// 地理位置,包括国家和地区
  35.         ///</summary>
  36.         public struct IPLocation
  37.         {
  38.             public string country, area;
  39.         }
  40.         ///<summary>
  41.         /// 获取指定IP所在地理位置
  42.         ///</summary>
  43.         ///<param name="strIP">要查询的IP地址</param>
  44.         ///<returns></returns>
  45.         public IPLocation GetIPLocation(string strIP)
  46.         {
  47.             ip = IPToLong(strIP);
  48.             ipFile = new FileStream(ipfilePath, FileMode.Open, FileAccess.Read);
  49.             long[] ipArray = BlockToArray(ReadIPBlock());
  50.             long offset = SearchIP(ipArray, 0, ipArray.Length - 1) * 7 + 4;
  51.             ipFile.Position += offset;//跳过起始IP
  52.             ipFile.Position = ReadLongX(3) + 4;//跳过结束IP

  53.             IPLocation loc = new IPLocation();
  54.             int flag = ipFile.ReadByte();//读取标志
  55.             if (flag == 1)//表示国家和地区被转向
  56.             {
  57.                 ipFile.Position = ReadLongX(3);
  58.                 flag = ipFile.ReadByte();//再读标志
  59.             }
  60.             long countryOffset = ipFile.Position;
  61.             loc.country = ReadString(flag);

  62.             if (flag == 2)
  63.             {
  64.                 ipFile.Position = countryOffset + 3;
  65.             }
  66.             flag = ipFile.ReadByte();
  67.             loc.area = ReadString(flag);

  68.             ipFile.Close();
  69.             ipFile = null;
  70.             return loc;
  71.         }
  72.         ///<summary>
  73.         /// 将字符串形式的IP转换位long
  74.         ///</summary>
  75.         ///<param name="strIP"></param>
  76.         ///<returns></returns>
  77.         public long IPToLong(string strIP)
  78.         {
  79.             byte[] ip_bytes = new byte[8];
  80.             string[] strArr = strIP.Split(new char[] { '.' });
  81.             for (int i = 0; i < 4; i++)
  82.             {
  83.                 ip_bytes[i] = byte.Parse(strArr[3 - i]);
  84.             }
  85.             return BitConverter.ToInt64(ip_bytes, 0);
  86.         }
  87.         ///<summary>
  88.         /// 将索引区字节块中的起始IP转换成Long数组
  89.         ///</summary>
  90.         ///<param name="ipBlock"></param>
  91.         long[] BlockToArray(byte[] ipBlock)
  92.         {
  93.             long[] ipArray = new long[ipBlock.Length / 7];
  94.             int ipIndex = 0;
  95.             byte[] temp = new byte[8];
  96.             for (int i = 0; i < ipBlock.Length; i += 7)
  97.             {
  98.                 Array.Copy(ipBlock, i, temp, 0, 4);
  99.                 ipArray[ipIndex] = BitConverter.ToInt64(temp, 0);
  100.                 ipIndex++;
  101.             }
  102.             return ipArray;
  103.         }
  104.         ///<summary>
  105.         /// 从IP数组中搜索指定IP并返回其索引
  106.         ///</summary>
  107.         ///<param name="ipArray">IP数组</param>
  108.         ///<param name="start">指定搜索的起始位置</param>
  109.         ///<param name="end">指定搜索的结束位置</param>
  110.         ///<returns></returns>
  111.         int SearchIP(long[] ipArray, int start, int end)
  112.         {
  113.             int middle = (start + end) / 2;
  114.             if (middle == start)
  115.                 return middle;
  116.             else if (ip < ipArray[middle])
  117.                 return SearchIP(ipArray, start, middle);
  118.             else
  119.                 return SearchIP(ipArray, middle, end);
  120.         }
  121.         ///<summary>
  122.         /// 读取IP文件中索引区块
  123.         ///</summary>
  124.         ///<returns></returns>
  125.         byte[] ReadIPBlock()
  126.         {
  127.             long startPosition = ReadLongX(4);
  128.             long endPosition = ReadLongX(4);
  129.             long count = (endPosition - startPosition) / 7 + 1;//总记录数
  130.             ipFile.Position = startPosition;
  131.             byte[] ipBlock = new byte[count * 7];
  132.             ipFile.Read(ipBlock, 0, ipBlock.Length);
  133.             ipFile.Position = startPosition;
  134.             return ipBlock;
  135.         }
  136.         ///<summary>
  137.         /// 从IP文件中读取指定字节并转换位long
  138.         ///</summary>
  139.         ///<param name="bytesCount">需要转换的字节数,主意不要超过8字节</param>
  140.         ///<returns></returns>
  141.         long ReadLongX(int bytesCount)
  142.         {
  143.             byte[] _bytes = new byte[8];
  144.             ipFile.Read(_bytes, 0, bytesCount);
  145.             return BitConverter.ToInt64(_bytes, 0);
  146.         }
  147.         ///<summary>
  148.         /// 从IP文件中读取字符串
  149.         ///</summary>
  150.         ///<param name="flag">转向标志</param>
  151.         ///<returns></returns>
  152.         string ReadString(int flag)
  153.         {
  154.             if (flag == 1 || flag == 2)//转向标志
  155.                 ipFile.Position = ReadLongX(3);
  156.             else
  157.                 ipFile.Position -= 1;

  158.             List<byte> list = new List<byte>();
  159.             byte b = (byte)ipFile.ReadByte();
  160.             while (b > 0)
  161.             {
  162.                 list.Add(b);
  163.                 b = (byte)ipFile.ReadByte();
  164.             }
  165.             return Encoding.Default.GetString(list.ToArray());
  166.         }
  167.     }
  168. }
复制代码
原创的免费软件 - LoopcVPN,DnsAcc,DNS加速器,百度相册助手
引用 TOP

支持分享
引用 TOP

看不懂呢
引用 TOP