C#读取纯真IP数据库方法

时间:2010年04月12日 点击:298



使用方法:
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);//地区
以下是基础类文件,和IP详细数据格式类

//根据LumaQQ改写而成.
using System;
using System.IO;
using System.Text;
namespace BDQQ.Data
{
/**//// <summary>
/// QQWry 的摘要说明。
/// </summary>

public class QQWry
{
//第一种模式
第一种模式
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 const string unCountry = "未知国家";
private const string unArea = "未知地区";
//索引开始位置
索引开始位置
private long ipBegin;
//索引结束位置
索引结束位置
private long ipEnd;
//IP地址对象
IP地址对象
private IPLocation loc;
//存储文本内容
存储文本内容
private byte[] buf;
//存储3字节
存储3字节
private byte[] b3;
//存储4字节
存储4字节
private byte[] b4;
//构造函数
构造函数
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地址搜索
根据IP地址搜索
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;
}


//取得具体信息
取得具体信息
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;
}


//取得地区信息
取得地区信息
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 );
}

}


//读取字符串
读取字符串
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地址所在的绝对偏移量
查找IP地址所在的绝对偏移量
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地址
读出4字节的IP地址
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地址是否相同
比较IP地址是否相同
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;
}


//比较两个字节是否相等
比较两个字节是否相等
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字节
根据当前位置读取4字节
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字节
根据当前位置,读取3字节
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字节
从当前位置读取3字节
private long readLong3()
{
long ret = 0;
ret
|= ( ipFile.ReadByte() & 0xFF );
ret
|= ( (ipFile.ReadByte() << 8 ) & 0xFF00 );
ret
|= ( (ipFile.ReadByte() << 16 ) & 0xFF0000 );
return ret;
}


//取得begin和end之间的偏移量
取得begin和end之间的偏移量
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;
}

}

}


www.zdexe.com

赞助商链接

热门内容

相关内容

联系我们

联系方式