欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#读取QQ纯真IP数据库QQWry.Dat的代码

程序员文章站 2023-10-30 15:18:04
纯真版qq ip数据库 复制代码 代码如下: using system; using system.collections.generic; using system.te...

纯真版qq ip数据库

复制代码 代码如下:

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;
}
}
}