C#读取QQ纯真IP数据库QQWry.Dat的代码
程序员文章站
2022-06-03 11:39:31
纯真版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;
}
}
}