纯真IP数据库

相关类(转):
View Code 
    /// <summary>
    
///QQWry 的摘要说明
    //纯真版QQ IP数据库下载:http://www.cz88.net/fox/
    /// </summary>
    public class QQWry
    {
        //Singleton
        static QQWry instance;
        public static QQWry GetInstance(string dataPath)
        {
            if (instance == null)
                instance = new QQWry(dataPath);

            return instance;
        }


        //第一种模式
        private const byte REDIRECT_MODE_1 = 0x01;

        //第二种模式
        private const byte REDIRECT_MODE_2 = 0x02;

        //每条记录长度
        private const int IP_RECORD_LENGTH = 7;

        //数据库文件
        private FileStream ipFile;
        private string ipFile2;

        private const string unCountry = "未知国家";
        private const string unArea = "未知地区";

        //索引开始位置
        private long ipBegin;

        //索引结束位置
        private long ipEnd;

        //IP地址对象
        private QQIPLocation loc;

        //存储文本内容
        private byte[] buf;

        //存储3字节
        private byte[] b3;

        //存储4字节
        private byte[] b4;

        /// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="ipfile">IP数据库文件绝对路径</param>
        
/// <returns></returns>
        public QQWry(string ipfile)
        {

            buf = new byte[100];
            b3 = new byte[3];
            b4 = new byte[4];
            ipFile2 = ipfile;

        }

        /// <summary>
        
/// 搜索IP地址搜索
        
/// </summary>
        
/// <param name="ip"></param>
        
/// <returns></returns>
        public QQIPLocation SearchIPLocation(string ip)
        {
            try
            {
                ipFile = new FileStream(ipFile2, FileMode.Open);

                ipBegin = readLong4(0);
                ipEnd = readLong4(4);
                loc = new QQIPLocation();


                //将字符IP转换为字节
                string[] ipSp = ip.Split('.');
                if (ipSp.Length != 4)
                {
                    throw new ArgumentOutOfRangeException("不是合法的IP地址!");
                }
                byte[] IP = new byte[4];
                for (int i = 0; i < IP.Length; i++)
                {
                    IP[i] = (byte)(Int32.Parse(ipSp[i]) & 0xFF);
                }

                QQIPLocation local = null;
                long offset = locateIP(IP);

                if (offset != -1)
                {
                    local = getIPLocation(offset);
                }

                if (local == null)
                {
                    local = new QQIPLocation();
                    local.area = unArea;
                    local.country = unCountry;
                }

                ipFile.Dispose();

                return local;
            }
            catch
            {
                return new QQIPLocation();
            }
            finally
            {
                ipFile.Dispose();
            }
        }

        /// <summary>
        
/// 取得具体信息
        
/// </summary>
        
/// <param name="offset"></param>
        
/// <returns></returns>
        private QQIPLocation getIPLocation(long offset)
        {
            ipFile.Position = offset + 4;
            //读取第一个字节判断是否是标志字节
            byte one = (byte)ipFile.ReadByte();
            if (one == REDIRECT_MODE_1)
            {
                //第一种模式
                
//读取国家偏移
                long countryOffset = readLong3();
                //转至偏移处
                ipFile.Position = countryOffset;
                //再次检查标志字节
                byte b = (byte)ipFile.ReadByte();
                if (b == REDIRECT_MODE_2)
                {
                    loc.country = readString(readLong3());
                    ipFile.Position = countryOffset + 4;
                }
                else
                    loc.country = readString(countryOffset);

                //读取地区标志
                loc.area = readArea(ipFile.Position);

            }
            else if (one == REDIRECT_MODE_2)
            {
                //第二种模式
                loc.country = readString(readLong3());
                loc.area = readArea(offset + 8);
            }
            else
            {
                //普通模式
                loc.country = readString(--ipFile.Position);
                loc.area = readString(ipFile.Position);
            }
            return loc;
        }

        /// <summary>
        
/// 读取地区名称
        
/// </summary>
        
/// <param name="offset"></param>
        
/// <returns></returns>
        private string readArea(long offset)
        {
            ipFile.Position = offset;
            byte one = (byte)ipFile.ReadByte();
            if (one == REDIRECT_MODE_1 || one == REDIRECT_MODE_2)
            {
                long areaOffset = readLong3(offset + 1);
                if (areaOffset == 0)
                    return unArea;
                else
                {
                    return readString(areaOffset);
                }
            }
            else
            {
                return readString(offset);
            }
        }

        /// <summary>
        
/// 读取字符串
        
/// </summary>
        
/// <param name="offset"></param>
        
/// <returns></returns>
        private string readString(long offset)
        {
            ipFile.Position = offset;
            int i = 0;
            for (i = 0, buf[i] = (byte)ipFile.ReadByte(); buf[i] != (byte)(0); buf[++i] = (byte)ipFile.ReadByte()) ;

            if (i > 0)
                return Encoding.Default.GetString(buf, 0, i);
            else
                return "";
        }

        /// <summary>
        
/// 查找IP地址所在的绝对偏移量
        
/// </summary>
        
/// <param name="ip"></param>
        
/// <returns></returns>
        private long locateIP(byte[] ip)
        {
            long m = 0;
            int r;

            //比较第一个IP项
            readIP(ipBegin, b4);
            r = compareIP(ip, b4);
            if (r == 0)
                return ipBegin;
            else if (r < 0)
                return -1;
            //开始二分搜索
            for (long i = ipBegin, j = ipEnd; i < j; )
            {
                m = this.getMiddleOffset(i, j);
                readIP(m, b4);
                r = compareIP(ip, b4);
                if (r > 0)
                    i = m;
                else if (r < 0)
                {
                    if (m == j)
                    {
                        j -= IP_RECORD_LENGTH;
                        m = j;
                    }
                    else
                    {
                        j = m;
                    }
                }
                else
                    return readLong3(m + 4);
            }
            m = readLong3(m + 4);
            readIP(m, b4);
            r = compareIP(ip, b4);
            if (r <= 0)
                return m;
            else
                return -1;
        }

        /// <summary>
        
/// 从当前位置读取四字节,此四字节是IP地址
        
/// </summary>
        
/// <param name="offset"></param>
        
/// <param name="ip"></param>
        private void readIP(long offset, byte[] ip)
        {
            ipFile.Position = offset;
            ipFile.Read(ip, 0, ip.Length);
            byte tmp = ip[0];
            ip[0] = ip[3];
            ip[3] = tmp;
            tmp = ip[1];
            ip[1] = ip[2];
            ip[2] = tmp;
        }

        /// <summary>
        
/// 比较IP地址是否相同
        
/// </summary>
        
/// <param name="ip"></param>
        
/// <param name="beginIP"></param>
        
/// <returns>0:相等,1:ip大于beginIP,-1:小于</returns>
        private int compareIP(byte[] ip, byte[] beginIP)
        {
            for (int i = 0; i < 4; i++)
            {
                int r = compareByte(ip[i], beginIP[i]);
                if (r != 0)
                    return r;
            }
            return 0;
        }

        /// <summary>
        
/// 比较两个字节是否相等
        
/// </summary>
        
/// <param name="bsrc"></param>
        
/// <param name="bdst"></param>
        
/// <returns></returns>
        private int compareByte(byte bsrc, byte bdst)
        {
            if ((bsrc & 0xFF) > (bdst & 0xFFL))
                return 1;
            else if ((bsrc ^ bdst) == 0)
                return 0;
            else
                return -1;
        }

        /// <summary>
        
/// 从当前位置读取4字节,转换为长整型
        
/// </summary>
        
/// <param name="offset"></param>
        
/// <returns></returns>
        private long readLong4(long offset)
        {
            long ret = 0;
            ipFile.Position = offset;
            ret |= (ipFile.ReadByte() & 0xFFL);
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00L);
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000L);
            ret |= ((ipFile.ReadByte() << 24) & 0xFF000000L);
            return ret;
        }

        /// <summary>
        
/// 根据当前位置,读取3字节
        
/// </summary>
        
/// <param name="offset"></param>
        
/// <returns></returns>
        private long readLong3(long offset)
        {
            long ret = 0;
            ipFile.Position = offset;
            ret |= (ipFile.ReadByte() & 0xFFL);
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00L);
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000L);
            return ret;
        }

        /// <summary>
        
/// 从当前位置读取3字节
        
/// </summary>
        
/// <returns></returns>
        private long readLong3()
        {
            long ret = 0;
            ret |= (ipFile.ReadByte() & 0xFFL);
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00L);
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000L);
            return ret;
        }

        /// <summary>
        
/// 取得begin和end中间的偏移
        
/// </summary>
        
/// <param name="begin"></param>
        
/// <param name="end"></param>
        
/// <returns></returns>
        private long getMiddleOffset(long begin, long end)
        {
            long records = (end - begin) / IP_RECORD_LENGTH;
            records >>= 1;
            if (records == 0)
                records = 1;
            return begin + records * IP_RECORD_LENGTH;
        } 
    }

    public class QQIPLocation
    {
        public String country;
        public String area;

        public String Prvoince
        {
            get
            {
                if (string.IsNullOrEmpty(country))
                    return "";

                int pos = country.IndexOf("");
                if (pos == -1)
                    return "";

                return country.Substring(0, country.Length - pos - 2);
            }
        }

        public String City
        {
            get
            {
                if (string.IsNullOrEmpty(country))
                    return "";

                int start = country.IndexOf("");
                int pos = country.IndexOf("");
                if (pos == -1)
                    return "";

                return country.Substring(start + 1, pos - start - 1);
            }
        }

        public QQIPLocation()
        {
            country = area = "";
        }

        public QQIPLocation getCopy()
        {
            QQIPLocation ret = new QQIPLocation();
            ret.country = country;
            ret.area = area;
            return ret;
        }

调用方法:
var wry = QQWry.GetInstance(page.Server.MapPath("~/QQWry.Dat"));
var location = wry.SearchIPLocation("60.191.244.5");

附件:

纯真IP数据库 

原文地址:https://www.cnblogs.com/Death/p/2668590.html