介绍文章
请参见下面的文章学习如何读取纯真ip数据库的细节
代码及使用方法
使用方法
本类可以直接使用
- 引入ip数据库解析类
- 调用init()函数进行初始化
- 使用getIpLctn(string ipStr)函数获取具体的ip地址
效果演示
具体代码
/// <summary>
/// By: YoseZang 2022.09
/// </summary>
internal class Program
{
static uint frstIdx;
static uint lstIdx;
static FileStream fs;
static BinaryReader br;
static object lckRd = new object();
/// <summary>
/// 首先调用该函数进行初始化
/// </summary>
public static void init()
{
try
{
fs = new FileStream("QQWry.dat", FileMode.Open, FileAccess.Read);
br = new BinaryReader(fs);
}
catch
{
fs= null;
br = null;
return;
}
//获取索引区的位置
frstIdx = br.ReadUInt32();
lstIdx = br.ReadUInt32();
}
/// <summary>
/// 检查字符串格式的ip地址是否合法
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
static bool chkIpLgl(string ip)
{
Regex rgx = new Regex(@"^(([1-9]|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}([1-9]|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$");
bool rslt;
rslt = rgx.IsMatch(ip);
return rslt;
}
//获取ip地址的int形式
static uint getIntIp(string ip)
{
string ipHdl = ip.Trim();
if (chkIpLgl(ip)==false)
{
return 0;
}
string[] strArr = ip.Split(new string[] { "."}, StringSplitOptions.RemoveEmptyEntries);
if (strArr.Length<4)
{
return 0;
}
uint adrs = 0;
adrs = Convert.ToUInt32(strArr[3]) + Convert.ToUInt32(strArr[2]) * 256 + Convert.ToUInt32(strArr[1]) * 256 * 256
+ Convert.ToUInt32(strArr[0]) * 256 * 256 * 256;
return adrs;
}
//获取ip地址的字符串形式
static string getStrIp(uint ip)
{
string adrs;
adrs = "";
adrs = "." + ip % 256;
ip = ip / 256;
adrs = "." + ip % 256+adrs;
ip = ip / 256;
adrs = "." + ip % 256 + adrs;
ip = ip / 256;
adrs = ip % 256 + adrs;
return adrs;
}
/// <summary>
/// 获取指定偏移处的uint形式的ip地址
/// </summary>
/// <param name="pstn"></param>
/// <returns></returns>
static uint getIpAtOfst(uint pstn)
{
br.BaseStream.Seek(pstn, SeekOrigin.Begin);
uint ip = br.ReadUInt32();
return ip;
}
/// <summary>
/// 根据偏移获取指定的位置的3字节文件偏移量数据
/// </summary>
/// <param name="pstn"></param>
/// <returns></returns>
static uint get3BytOfst(uint pstn)
{
br.BaseStream.Seek(pstn, SeekOrigin.Begin);
byte[] bytArr;
bytArr = br.ReadBytes(3);
uint ofst = (uint)bytArr[0] + (uint)bytArr[1] * 256 + (uint)bytArr[2] * 256 * 256;
return ofst;
}
/// <summary>
/// 根据偏移获取指定的偏移处1字节
/// </summary>
/// <param name="pstn"></param>
/// <returns></returns>
static byte getBytAtPstn(uint pstn)
{
br.BaseStream.Seek(pstn, SeekOrigin.Begin);
byte byt;
byt = br.ReadByte();
return byt;
}
/// <summary>
/// 根据偏移获取指定的偏移处的字符串
/// </summary>
/// <param name="pstn"></param>
/// <returns></returns>
static string getStrAtPstn(uint pstn)
{
br.BaseStream.Seek(pstn, SeekOrigin.Begin);
byte[] bytArr=new byte[0x500];
byte byt;
int sz=0;
do
{
byt = br.ReadByte();
bytArr[sz] = byt;
sz++;
}
while (byt != 0);
string str = Encoding.Default.GetString(bytArr,0,sz-1);
return str;
}
/// <summary>
/// 根据偏移获取指定的偏移处的字符串之后的1字节
/// </summary>
/// <param name="pstn"></param>
/// <returns></returns>
static byte getBytAftStrAtPstn(uint pstn)
{
br.BaseStream.Seek(pstn, SeekOrigin.Begin);
byte byt;
do
{
byt = br.ReadByte();
}
while (byt != 0);
byt = br.ReadByte();
//Console.WriteLine("读取的字节是:"+byt );
return byt;
}
/// <summary>
/// 根据偏移获取指定的偏移处的字符串之后的位置
/// </summary>
/// <param name="pstn"></param>
/// <returns></returns>
static uint getOfstAftStrAtPstn(uint pstn)
{
br.BaseStream.Seek(pstn, SeekOrigin.Begin);
byte[] bytArr = new byte[0x500];
byte byt;
int sz = 0;
do
{
byt = br.ReadByte();
bytArr[sz] = byt;
sz++;
}
while (byt != 0);
return (uint)br.BaseStream.Position;
}
/// <summary>
/// 根据偏移获取指定的偏移处的第二个字符串
/// </summary>
/// <param name="pstn"></param>
/// <returns></returns>
static string getScndStrAtPstn(uint pstn)
{
br.BaseStream.Seek(pstn, SeekOrigin.Begin);
byte[] bytArr = new byte[0x500];
int sz = 0;
byte byt;
do
{
byt = br.ReadByte();
}
while (byt != 0);
do
{
byt = br.ReadByte();
bytArr[sz] = byt;
sz++;
}
while (byt != 0);
string str = Encoding.Default.GetString(bytArr, 0, sz-1);
return str;
}
/// <summary>
/// 获取ip地址索引的位置
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
static uint getIdxOfst(uint ip)
{
uint lPstn = frstIdx;
uint rPstn = lstIdx;
uint mPstn, ipMPstn;
while (lPstn < rPstn)
{
mPstn = ((rPstn-lPstn)%14==0) ? ( (rPstn - lPstn) / 2 + lPstn) : ((rPstn - lPstn- 7)/2+lPstn);
ipMPstn = getIpAtOfst(mPstn);
//Console.WriteLine("mPstn:" + mPstn +" 记录:"+ipMPstn);
//Thread.Sleep(1000);
if (ipMPstn > ip)
{
rPstn = mPstn;
}
else if (ipMPstn < ip)
{
lPstn = mPstn;
}
else if (ipMPstn==ip)
{
lPstn = mPstn;
rPstn = mPstn;
}
if (rPstn == lPstn + 7)
{
break;
}
}
return lPstn;
}
static string getIpDt(uint ofst)
{
byte bytSgn;
bytSgn = getBytAtPstn(ofst + 4);
string dt, dt2;
dt = String.Empty;
dt2 = String.Empty;
// 模式1 连续存放数据的情况
if (bytSgn != 0x01 && bytSgn != 0x02)
{
//Console.WriteLine("模式1");
br.BaseStream.Seek(ofst + 4, SeekOrigin.Begin);
dt = getStrAtPstn(ofst + 4);
dt2 = getScndStrAtPstn(ofst + 4);
}
// 记录模式2 4 5
if (bytSgn == 0x01)
{
//Console.WriteLine("模式245");
uint dtOfst = get3BytOfst(ofst + 5);
//Console.WriteLine("字符串之后的数据:" + getBytAftStrAtPstn(dtOfst));
// 记录模式 2
if (getBytAtPstn(dtOfst) !=0x01 && getBytAtPstn(dtOfst)!=0x02)
{
//Console.WriteLine("模式2");
dt = getStrAtPstn(dtOfst);
//Console.WriteLine("记录A:"+dt);
if (getBytAftStrAtPstn(dtOfst) != 0x01 && getBytAftStrAtPstn(dtOfst) != 0x02)
{
dt2 = getScndStrAtPstn(dtOfst);
}
else
{
uint dtOfst2 = get3BytOfst( getOfstAftStrAtPstn(dtOfst)+1);
dt2 = getStrAtPstn(dtOfst2);
}
//Console.WriteLine("记录B:" + Encoding.Default.GetBytes(dt2).ToString());
}
// 记录模式4 5
else if (getBytAtPstn(dtOfst)==0x02)
{
//Console.WriteLine("模式45");
// 记录模式4
if (getBytAtPstn(dtOfst + 4) != 0x01 && getBytAtPstn(dtOfst + 4) != 0x02)
{
//Console.WriteLine("模式4");
uint dtOfst2 = get3BytOfst(dtOfst + 1);
dt = getStrAtPstn(dtOfst2);
dt2 = getStrAtPstn(dtOfst + 4);
}
// 记录模式5
else
{
//Console.WriteLine("模式5");
uint dtOfst2 = get3BytOfst(dtOfst + 1);
dt = getStrAtPstn(dtOfst2);
uint dtOfst3 = get3BytOfst(dtOfst + 5);
if (dtOfst3 != 0)
{
dt2 = getStrAtPstn(dtOfst3);
}
}
}
}
// 记录模式3 记录A被重定向
if (bytSgn == 0x02)
{
//Console.WriteLine("模式3");
uint dtOfst = get3BytOfst(ofst + 5);
dt = getStrAtPstn(dtOfst);
dt2 = getStrAtPstn(ofst + 8);
}
if (dt.Contains("CZ88.NET"))
{
dt = String.Empty;
}
if (dt2.Contains("CZ88.NET"))
{
dt2 = String.Empty;
}
return dt + " " + dt2;
}
public static string getIpLctn(string ipStr)
{
uint ip, idxOfst, dtOfst;
string str;
lock (lckRd)
{
if (chkIpLgl(ipStr) == false)
{
return String.Empty;
}
ip = getIntIp(ipStr);
idxOfst = getIdxOfst(ip);
dtOfst = get3BytOfst(idxOfst + 4);
str = string.Empty;
str = getIpDt(dtOfst);
Console.WriteLine("位置信息:"+str);
//MessageBox.Show(str);
}
return str;
}
/// <summary>
/// 测试函数
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
init();
string ipStr;
while (true)
{
Console.Write("请输入Ip地址:");
ipStr = Console.ReadLine();
Console.WriteLine("匹配ip地址规则:" + chkIpLgl(ipStr));
Console.WriteLine(getIpLctn(ipStr));
}
Console.ReadLine();
}
}