程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#讀取QQWry.Dat文件實現IP查詢

C#讀取QQWry.Dat文件實現IP查詢

編輯:C#入門知識

 [csharp]
using System; 
 
using System.Collections.Generic; 
 
using System.Text; 
 
using System.IO; 
 
using System.Web; 
 
using System.Configuration; 
 
 
 
namespace BLL 
 

 
    public class IPLocationSearch 
 
    { 
 
        private static readonly QQWry qq = new QQWry(ConfigurationManager.AppSettings["ip"] + "qqwry.dat"); 
 
 
 
        public static IPLocation GetIPLocation(string ip) 
 
        { 
 
            return qq.SearchIPLocation(ip); 
 
        } 
 
    } 
 
 
 
    /*
 
    使用方法:
 
 
 
    例子:
 
    BDQQ.Data.QQWry qq=new BDQQ.Data.QQWry("d:\\QQWry.Dat");
 
    BDQQ.Data.IPLocation ip=qq.SearchIPLocation("127.0.0.1");//這裡添寫IP地址
 
    Console.WriteLine(ip.country);//國家
 
    Console.WriteLine(ip.area);//地區
 
    */ 
 
 
 
    //以下是類文件 
 
    //根據LumaQQ改寫而成. 
 
 
 
    /**/ 
 
    ///<summary> 
 
    /// QQWry 的摘要說明。 
 
    ///</summary> 
 
    public class QQWry 
 
    { 
 
        //第一種模式 
 
        #region 第一種模式 
 
        /**/ 
 
        ///<summary> 
 
        ///第一種模式 
 
        ///</summary> 
 
        #endregion 
 
        private const byte REDIRECT_MODE_1 = 0x01; 
 
 
 
        //第二種模式 
 
        #region 第二種模式 
 
        /**/ 
 
        ///<summary> 
 
        ///第二種模式 
 
        ///</summary> 
 
        #endregion 
 
        private const byte REDIRECT_MODE_2 = 0x02; 
 
 
 
        //每條記錄長度 
 
        #region 每條記錄長度 
 
        /**/ 
 
        ///<summary> 
 
        ///每條記錄長度 
 
        ///</summary> 
 
        #endregion 
 
        private const int IP_RECORD_LENGTH = 7; 
 
 
 
        //數據庫文件 
 
        #region 數據庫文件 
 
        /**/ 
 
        ///<summary> 
 
        ///文件對象 
 
        ///</summary> 
 
        #endregion 
 
        private FileStream ipFile; 
 
 
 
        private const string unCountry = "未知國家"; 
 
        private const string unArea = "未知地區"; 
 
 
 
        //索引開始位置 
 
        #region 索引開始位置 
 
        /**/ 
 
        ///<summary> 
 
        ///索引開始位置 
 
        ///</summary> 
 
        #endregion 
 
        private long ipBegin; 
 
 
 
        //索引結束位置 
 
        #region 索引結束位置 
 
        /**/ 
 
        ///<summary> 
 
        ///索引結束位置 
 
        ///</summary> 
 
        #endregion 
 
        private long ipEnd; 
 
 
 
        //IP地址對象 
 
        #region  IP地址對象 
 
        /**/ 
 
        ///<summary> 
 
        /// IP對象 
 
        ///</summary> 
 
        #endregion 
 
        private IPLocation loc; 
 
 
 
        //存儲文本內容 
 
        #region 存儲文本內容 
 
        /**/ 
 
        ///<summary> 
 
        ///存儲文本內容 
 
        ///</summary> 
 
        #endregion 
 
        private byte[] buf; 
 
 
 
        //存儲3字節 
 
        #region 存儲3字節 
 
        /**/ 
 
        ///<summary> 
 
        ///存儲3字節 
 
        ///</summary> 
 
        #endregion 
 
        private byte[] b3; 
 
 
 
        //存儲4字節 
 
        #region 存儲4字節 
 
        /**/ 
 
        ///<summary> 
 
        ///存儲4字節IP地址 
 
        ///</summary> 
 
        #endregion 
 
        private byte[] b4; 
 
 
 
        //構造函數 
 
        #region 構造函數 
 
        /**/ 
 
        ///<summary> 
 
        ///構造函數 
 
        ///</summary> 
 
        ///<param name="ipfile">IP數據庫文件絕對路徑</param> 
 
        #endregion 
 
        public QQWry(string ipfile) 
 
        { 
 
 
 
            buf = new byte[100]; 
 
            b3 = new byte[3]; 
 
            b4 = new byte[4]; 
 
            try 
 
            { 
 
                ipFile = new FileStream(ipfile, FileMode.Open); 
 
            } 
 
            catch (Exception ex) 
 
            { 
 
                throw new Exception(ex.Message); 
 
            } 
 
            ipBegin = readLong4(0); 
 
            ipEnd = readLong4(4); 
 
            loc = new IPLocation(); 
 
        } 
 
 
 
        //根據IP地址搜索 
 
        #region 根據IP地址搜索 
 
        /**/ 
 
        ///<summary> 
 
        ///搜索IP地址搜索 
 
        ///</summary> 
 
        ///<param name="ip"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        public IPLocation SearchIPLocation(string ip) 
 
        { 
 
            //將字符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); 
 
            } 
 
 
 
            IPLocation local = null; 
 
            long offset = locateIP(IP); 
 
 
 
            if (offset != -1) 
 
            { 
 
                local = getIPLocation(offset); 
 
            } 
 
 
 
            if (local == null) 
 
            { 
 
                local = new IPLocation(); 
 
                local.area = unArea; 
 
                local.country = unCountry; 
 
            } 
 
            return local; 
 
        } 
 
 
 
        //取得具體信息 
 
        #region 取得具體信息 
 
        /**/ 
 
        ///<summary> 
 
        ///取得具體信息 
 
        ///</summary> 
 
        ///<param name="offset"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        private IPLocation 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; 
 
        } 
 
 
 
        //取得地區信息 
 
        #region 取得地區信息 
 
        /**/ 
 
        ///<summary> 
 
        ///讀取地區名稱 
 
        ///</summary> 
 
        ///<param name="offset"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        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); 
 
            } 
 
        } 
 
 
 
        //讀取字符串 
 
        #region 讀取字符串 
 
        /**/ 
 
        ///<summary> 
 
        ///讀取字符串 
 
        ///</summary> 
 
        ///<param name="offset"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        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 ""; 
 
        } 
 
 
 
        //查找IP地址所在的絕對偏移量 
 
        #region 查找IP地址所在的絕對偏移量 
 
        /**/ 
 
        ///<summary> 
 
        ///查找IP地址所在的絕對偏移量 
 
        ///</summary> 
 
        ///<param name="ip"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        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; 
 
        } 
 
 
 
        //讀出4字節的IP地址 
 
        #region 讀出4字節的IP地址 
 
        /**/ 
 
        ///<summary> 
 
        ///從當前位置讀取四字節,此四字節是IP地址 
 
        ///</summary> 
 
        ///<param name="offset"></param> 
 
        ///<param name="ip"></param> 
 
        #endregion 
 
        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; 
 
        } 
 
 
 
        //比較IP地址是否相同 
 
        #region 比較IP地址是否相同 
 
        /**/ 
 
        ///<summary> 
 
        ///比較IP地址是否相同 
 
        ///</summary> 
 
        ///<param name="ip"></param> 
 
        ///<param name="beginIP"></param> 
 
        ///<returns>0:相等,1:ip大於beginIP,-1:小於</returns> 
 
        #endregion 
 
        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; 
 
        } 
 
 
 
        //比較兩個字節是否相等 
 
        #region 比較兩個字節是否相等 
 
        /**/ 
 
        ///<summary> 
 
        ///比較兩個字節是否相等 
 
        ///</summary> 
 
        ///<param name="bsrc"></param> 
 
        ///<param name="bdst"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        private int compareByte(byte bsrc, byte bdst) 
 
        { 
 
            if ((bsrc & 0xFF) > (bdst & 0xFF)) 
 
                return 1; 
 
            else if ((bsrc ^ bdst) == 0) 
 
                return 0; 
 
            else 
 
                return -1; 
 
        } 
 
 
 
        //根據當前位置讀取4字節 
 
        #region 根據當前位置讀取4字節 
 
        /**/ 
 
        ///<summary> 
 
        ///從當前位置讀取4字節,轉換為長整型 
 
        ///</summary> 
 
        ///<param name="offset"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        private long readLong4(long offset) 
 
        { 
 
            long ret = 0; 
 
            ipFile.Position = offset; 
 
            ret |= (ipFile.ReadByte() & 0xFF); 
 
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00); 
 
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000); 
 
            ret |= ((ipFile.ReadByte() << 24) & 0xFF000000); 
 
            return ret; 
 
        } 
 
 
 
        //根據當前位置,讀取3字節 
 
        #region 根據當前位置,讀取3字節 
 
        /**/ 
 
        ///<summary> 
 
        ///根據當前位置,讀取3字節 
 
        ///</summary> 
 
        ///<param name="offset"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        private long readLong3(long offset) 
 
        { 
 
            long ret = 0; 
 
            ipFile.Position = offset; 
 
            ret |= (ipFile.ReadByte() & 0xFF); 
 
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00); 
 
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000); 
 
            return ret; 
 
        } 
 
 
 
        //從當前位置讀取3字節 
 
        #region 從當前位置讀取3字節 
 
        /**/ 
 
        ///<summary> 
 
        ///從當前位置讀取3字節 
 
        ///</summary> 
 
        ///<returns></returns> 
 
        #endregion 
 
        private long readLong3() 
 
        { 
 
            long ret = 0; 
 
            ret |= (ipFile.ReadByte() & 0xFF); 
 
            ret |= ((ipFile.ReadByte() << 8) & 0xFF00); 
 
            ret |= ((ipFile.ReadByte() << 16) & 0xFF0000); 
 
            return ret; 
 
        } 
 
 
 
        //取得begin和end之間的偏移量 
 
        #region 取得begin和end之間的偏移量 
 
        /**/ 
 
        ///<summary> 
 
        ///取得begin和end中間的偏移 
 
        ///</summary> 
 
        ///<param name="begin"></param> 
 
        ///<param name="end"></param> 
 
        ///<returns></returns> 
 
        #endregion 
 
        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; 
 
        } 
 
    } //class QQWry 
 
 
 
    public class IPLocation 
 
    { 
 
        public String country; 
 
        public String area; 
 
 
 
        public IPLocation() 
 
        { 
 
            country = area = ""; 
 
        } 
 
 
 
        public IPLocation getCopy() 
 
        { 
 
            IPLocation ret = new IPLocation(); 
 
            ret.country = country; 
 
            ret.area = area; 
 
            return ret; 
 
        } 
 
    } 
 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved