查看完整版本: 【原创】纯真IP数据库查询模块源代码参考(C#)

risingsun 2008-8-12 17:39

【原创】纯真IP数据库查询模块源代码参考(C#)

发一个自己写的C#的IP所在地查询程序,使用纯真/珊瑚虫数据库均可(QQWry.dat/CoralWry.dat),程序的实际使用价值可能不大,仅作为此类c#程序的参照。

有些朋友在C#中使用动态类对象的构造函数/析构函数在对象的初始化/释放时来打开/关闭数据文件,这虽然是一个很好的面向的思想,但托管程序对象的释放时间是不确定的,尤其是ASP.NET的使用,这一方面由于打开的文件未释放会造成资源浪费,更重要的是可能会带来线程并发所造成的共享冲突,另外如果在ASP.NET中使用缓存机制则会增加程序的复杂性和降低模块的独立性、重用性。

基于这些原因,[b][size=2]程序中全部使用静态方法[/size][/b],实际上这是由我的另一个C++的程序改写的C#程序,模块的调用很简单,例如,使用当前目录下的CoralWry.dat数据文件来查询IP地址121.193.213.6,则可以:
[code]
IpLocation ipl=IpLocation ipl=IpLocator.GetIpLocation("CoralWry.dat","121.193.213.246");
Console.WriteLine("IP地址段: "+IpLocator.IntToIpString(ipl.IpStart)+" - "+IpLocator.IntToIpString(ipl.IpEnd));
Console.WriteLine("IP所在地: "+ipl.Country+" "+ipl.City);

[/code]
返回值是一个IpLocation结构,包含4个属性:Country国家、City城市、IpStart/IpEnd IP段开始/结束值(uint型,可使用IntToIpString()函数转成点分IP字符串)

IpLocation.

[code]
//IpLocator.cs -> IpLocator.dll
using System;
using System.IO;
namespace Hebust
{
    /// <summary>
    /// IpLocator类
    /// </summary>
    public class IpLocator
    {
        // 核心方法:IP搜索
        public static IpLocation GetIpLocation(string fn, string ips)
        {
            if(!File.Exists(fn))
            {
                throw new Exception("文件不存在!");
            }
            FileStream fs=new FileStream(fn,FileMode.Open,FileAccess.Read,FileShare.Read);
            BinaryReader fp=new BinaryReader(fs);
            //读文件头,获取首末记录偏移量
            int fo=fp.ReadInt32();
            int lo=fp.ReadInt32();
            //IP值
            uint ipv=IpStringToInt(ips);
            // 获取IP索引记录偏移值
            int rcOffset=getIndexOffset(fs,fp,fo,lo,ipv);
            fs.Seek(rcOffset,System.IO.SeekOrigin.Begin);
            IpLocation ipl;
            if(rcOffset>=0)
            {
                fs.Seek(rcOffset,System.IO.SeekOrigin.Begin);
                //读取开头IP值
                ipl.IpStart=fp.ReadUInt32();
                //转到记录体
                fs.Seek(ReadInt24(fp),System.IO.SeekOrigin.Begin);
                //读取结尾IP值
                ipl.IpEnd=fp.ReadUInt32();
                ipl.Country=GetString(fs,fp);
                ipl.City=GetString(fs,fp);
            }
            else
            {
                //没找到
                ipl.IpStart=0;
                ipl.IpEnd=0;
                ipl.Country="未知国家";
                ipl.City="未知地址";
            }
            fp.Close();
            fs.Close();
            return ipl;
        }
   
        // 函数功能: 采用“二分法”搜索索引区, 定位IP索引记录位置
        private static int getIndexOffset(FileStream fs, BinaryReader fp, int _fo, int _lo, uint ipv)
        {
            int fo=_fo, lo=_lo;
            int mo;    //中间偏移量
            uint mv;    //中间值
            uint fv,lv; //边界值
            uint llv;   //边界末末值
            fs.Seek(fo,System.IO.SeekOrigin.Begin);
            fv=fp.ReadUInt32();
            fs.Seek(lo,System.IO.SeekOrigin.Begin);
            lv=fp.ReadUInt32();
            //临时作它用,末记录体偏移量
            mo=ReadInt24(fp);
            fs.Seek(mo,System.IO.SeekOrigin.Begin);
            llv=fp.ReadUInt32();
            //边界检测处理
            if(ipv<fv)
                return -1;
            else if(ipv>llv)
                return -1;
            //使用"二分法"确定记录偏移量
            do
            {
                mo=fo+(lo-fo)/7/2*7;
                fs.Seek(mo,System.IO.SeekOrigin.Begin);
                mv=fp.ReadUInt32();
                if(ipv>=mv)
                    fo=mo;
                else
                    lo=mo;
                if(lo-fo==7)
                    mo=lo=fo;
            } while(fo!=lo);
            return mo;
        }
        // 字符串数值型判断
        public static bool IsNumeric(string s)
        {
            if(s!=null && System.Text.RegularExpressions.Regex.IsMatch(s, @"^-?\d+$"))
                return true;
            else
                return false;
        }
        // IP字符串->长整型值
        public static uint IpStringToInt(string IpString)
        {
            uint Ipv=0;
            string[] IpStringArray=IpString.Split('.');
            int i;
            uint Ipi;
            for(i=0;i<4&&i<IpStringArray.Length;i++)
            {
                if(IsNumeric(IpStringArray[i]))
                {
                    Ipi=(uint)Math.Abs(Convert.ToInt32(IpStringArray[i]));
                    if(Ipi>255) Ipi=255;
                    Ipv+=Ipi<<(3-i)*8;
                }
            }
            return Ipv;
        }
        // 长整型值->IP字符串
        public static string IntToIpString(uint Ipv)
        {
            string IpString="";
            IpString+=(Ipv>>24)+"."+((Ipv&0x00FF0000)>>16)+"."+((Ipv&0x0000FF00)>>8)+"."+(Ipv&0x000000FF);
            return IpString;
        }
        // 读取字符串
        private static string ReadString(BinaryReader fp)
        {
            byte[] TempByteArray=new byte[128];
            int i=0;
            do
            {
                TempByteArray[i]=fp.ReadByte();
            } while(TempByteArray[i++]!='\0' && i<128);
            return System.Text.Encoding.Default.GetString(TempByteArray).TrimEnd('\0');
        }
        // 读取三字节的整数
        private static int ReadInt24(BinaryReader fp)
        {
            if(fp==null) return -1;
            int ret=0;
            ret|=(int)fp.ReadByte();
            ret|=(int)fp.ReadByte()<<8&0xFF00;
            ret|=(int)fp.ReadByte()<<16&0xFF0000;
            return ret;
        }
        // 读取IP所在地字符串
        private static string GetString(FileStream fs, BinaryReader fp)
        {
            byte Tag;
            int Offset;
            Tag=fp.ReadByte();
            if(Tag==0x01)        // 重定向模式1: 城市信息随国家信息定向
            {
                Offset=ReadInt24(fp);
                fs.Seek(Offset,System.IO.SeekOrigin.Begin);
                return GetString(fs,fp);
            }
            else if(Tag==0x02)    // 重定向模式2: 城市信息没有随国家信息定向
            {
                Offset=ReadInt24(fp);
                int TmpOffset=(int)fs.Position;
                fs.Seek(Offset,System.IO.SeekOrigin.Begin);
                string TmpString=GetString(fs,fp);
                fs.Seek(TmpOffset,System.IO.SeekOrigin.Begin);
                return TmpString;
            }
            else    // 无重定向: 最简单模式
            {
                fs.Seek(-1,System.IO.SeekOrigin.Current);
                return ReadString(fp);
            }
        }
    }
    // IP查询结果结构
    public struct IpLocation
    {
        public uint IpStart;
        public uint IpEnd;
        public string Country;
        public string City;
    }
}

[/code]

risingsun 2008-8-12 17:47

附C#工程文件(DLL工程,输出IpLocator.dll)

wyj717521 2008-11-24 10:46

不错啊~~我正要找这个呢
页: [1]
查看完整版本: 【原创】纯真IP数据库查询模块源代码参考(C#)