|
VS.NET读取纯真IP数据库(C#)
|
|
|
作者:yaosansi 发布时间:2006-12-30 23:08:08 | 【字体: 大 中 小】
|
使用方法:
例子: 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改写而成.
using System; using System.IO; using System.Text; namespace BDQQ.Data { /**//// /// QQWry 的摘要说明。 /// public class QQWry { //第一种模式 #region 第一种模式 /**//// /// 第一种模式 /// #endregion private const byte REDIRECT_MODE_1 = 0x01; //第二种模式 #region 第二种模式 /**//// /// 第二种模式 /// #endregion private const byte REDIRECT_MODE_2 = 0x02; //每条记录长度 #region 每条记录长度 /**//// /// 每条记录长度 /// #endregion private const int IP_RECORD_LENGTH = 7; //数据库文件 #region 数据库文件 /**//// /// 文件对象 /// #endregion private FileStream ipFile; private const string unCountry = "未知国家"; private const string unArea = "未知地区"; //索引开始位置 #region 索引开始位置 /**//// /// 索引开始位置 /// #endregion private long ipBegin; //索引结束位置 #region 索引结束位置 /**//// /// 索引结束位置 /// #endregion private long ipEnd; //IP地址对象 #region IP地址对象 /**//// /// IP对象 /// #endregion private IPLocation loc; //存储文本内容 #region 存储文本内容 /**//// /// 存储文本内容 /// #endregion private byte[] buf; //存储3字节 #region 存储3字节 /**//// /// 存储3字节 /// #endregion private byte[] b3; //存储4字节 #region 存储4字节 /**//// /// 存储4字节IP地址 /// #endregion private byte[] b4; //构造函数 #region 构造函数 /**//// /// 构造函数 /// /// IP数据库文件绝对路径 #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地址搜索 /**//// /// 搜索IP地址搜索 /// /// /// #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 取得具体信息 /**//// /// 取得具体信息 /// /// /// #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 取得地区信息 /**//// /// 读取地区名称 /// /// /// #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 读取字符串 /**//// /// 读取字符串 /// /// /// #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地址所在的绝对偏移量 /**//// /// 查找IP地址所在的绝对偏移量 /// /// /// #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地址 /**//// /// 从当前位置读取四字节,此四字节是IP地址 /// /// /// #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地址是否相同 /**//// /// 比较IP地址是否相同 /// /// /// /// 0:相等,1:ip大于beginIP,-1:小于 #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 比较两个字节是否相等 /**//// /// 比较两个字节是否相等 /// /// /// /// #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字节 /**//// /// 从当前位置读取4字节,转换为长整型 /// /// /// #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字节 /**//// /// 根据当前位置,读取3字节 /// /// /// #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字节 /**//// /// 从当前位置读取3字节 /// /// #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之间的偏移量 /**//// /// 取得begin和end中间的偏移 /// /// /// /// #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; } } }
原文地址:http://www.yaosansi.com/blog/article.asp?id=278
|
|
文章来源:yaosansis blog
|
|
|
·VS.NET2005智能感知失效的解决办法 ·VS.NET 2005 + VSS6.0简单应用示例 ·VS.NET2005 web程序自定义安装包的制作 ·完全卸载Visual Studio 2008 Beta2的步骤 ·Visual Studio 2008的常见问题 ·如何用VS.NET 2005制作安装程序 ·VS2005中的WebSite和WebApplication有何区别 ·使用.NET实现你的IP切换器 ·VS.NET 2005中使用MySQL 5.0 ·移除VS2005方案中的VSS绑定信息
|