📄 myipshow.c
字号:
//访问纯真IP数据库
//参考:纯真IP数据库格式详解
//date:2009/3/28
//author:芭蕉
//site:bajiaoye.cublog.cn
//usage: init("QQWry.dat") queryIp("11.11.11.11");
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define STRLEN 256
#define REDIRECT_MODE_1 0x01
#define REDIRECT_MODE_2 0x02
#define byte unsigned char
#define ulong unsigned long
/*IP记录由country、area两部分组成*/
typedef struct IPLocation_s
{
byte country[STRLEN];
byte area[STRLEN];
}IPLocation;
//纯真IP数据库头
typedef struct dbHeader_s
{
ulong firstStartIpOffset;
ulong lastStartIpOffset;
}dbHeader;
byte* data= NULL; //指向纯真IP数据库的指针
dbHeader dbheader; //IP数据库头
// 将纯真IP数据库中的所有数据读入全局数组data
int init(byte* file);
// 查询ipStr
IPLocation queryIp(byte* ipStr);
// 二分法获得IP记录偏移量
ulong getOffsetOfIp(ulong ip);
// 从索引区获得IP地址
ulong getIpFromIndex(ulong left,ulong* addr);
// 从记录区获得IP地址
ulong getIpFromRecord(ulong endIpOff);
// 将字符数组转成一个整数
ulong getInt32(byte* buf,int num);
// 将ip从字符串形式转化为一个长整数
ulong IpToLong(byte* ipStr);
// 给定一个ip国家地区记录的偏移,返回一个IPLocation结构
IPLocation getIPLocation(ulong offset);
// 从offset偏移开始解析后面的字节,读出一个地区名
int readArea(ulong offset,byte* buf);
// 将纯真IP数据库中的所有数据读入全局数组data
int readString(ulong offset,byte* buf);
int main()
{
IPLocation loc;
int ret;
if(1 == init("QQWry.dat"))
{
printf("初始化失败!\n");
return 1;
}
loc=queryIp("22.192.168.229");
printf("\n%s\t%s\n",loc.country,loc.area);
return 0;
}
// 功能:将纯真IP数据库中的所有数据读入全局数组data
// 参数:file 文件字符串
// 返回值: 0 成功
int init(byte* file)
{
ulong fileSize; //文件长度
FILE* fp ;
fp=fopen(file,"rb");
if(fp == NULL)
return 1;
//获取文件长度
fseek(fp, 0, SEEK_END);
fileSize = ftell(fp);
//将纯真IP数据库中的所有数据读入数组
data=(byte*)malloc(fileSize* sizeof(byte));
fseek(fp,0,SEEK_SET);
fread(data,1,fileSize,fp);
if(data == NULL)
return 2;
fclose(fp);
fp=NULL;
//读取IP数据库文件头
dbheader.firstStartIpOffset=getInt32(&data[0],4);
dbheader.lastStartIpOffset=getInt32(&data[4],4);
//printf("%ld %ld \n",dbheader.firstStartIpOffset,dbheader.lastStartIpOffset);
return 0;
}
// 功能:查询ipStr
IPLocation queryIp(byte* ipStr)
{
ulong ip;
ulong offset;
ip=IpToLong(ipStr);
offset=getOffsetOfIp(ip);
//printf("ip:%u ,offset: %u",ip,offset);
return getIPLocation(offset);
}
//功能: 二分法获得IP记录偏移量
//参数:ip 待查询ip
//返回值:相对于文件头的偏移量 (0 失败)
ulong getOffsetOfIp(ulong ip)
{
ulong low=0;
ulong high=(dbheader.lastStartIpOffset-dbheader.firstStartIpOffset)/7;
ulong endIpOff;
ulong mid;
while(low<high-1)
{
mid=(low+high)/2;
if(ip<getIpFromIndex(mid,&endIpOff))
high=mid;
else
low=mid;
}
//printf("\nlow:%ld \n",low);
if(ip>=getIpFromIndex(low,&endIpOff)&&ip<=getIpFromRecord(endIpOff))
{
return endIpOff;
}
return 0L;
}
// 功能:从索引区获得IP地址
// 参数:left 索引
// 返回值:起始Ip地址
// endIpOff 该索引所对应的结束Ip偏移量
ulong getIpFromIndex(ulong left,ulong* addr)
{
ulong leftOffset = dbheader.firstStartIpOffset + (left * 7L);
*addr=getInt32(&data[leftOffset+4],3);
return getInt32(&data[leftOffset],4);
}
// 功能:从记录区获得IP地址
ulong getIpFromRecord(ulong endIpOff)
{
return getInt32(&data[endIpOff],4);
}
// 功能:将字符数组转成一个整数
ulong getInt32(byte* buf,int num)
{
ulong ret=0;
int i;
for(i=0;i<num;i++)
{
ret+=(buf[i]<<(8*i));
}
return ret ;
}
//将ip从字符串形式转化为一个长整数
ulong IpToLong(byte* ipStr)
{
byte* p=ipStr;
byte ch;
int i=0;
int shift=24;
ulong ret=0,temp;
for(i=0;i<4;i++)
{
temp=0;
while((ch=*p++)!='.' && ch)
temp=temp*10+(ch -'0');
ret+=(temp<<shift);
shift-=8;
}
if(i!=4)
return -1;
return ret;
}
// 功能:给定一个ip国家地区记录的偏移,返回一个IPLocation结构
// 参数: offset 国家记录的起始偏移
// 返回值:IPLocation对象
IPLocation getIPLocation(ulong offset)
{
IPLocation loc;
byte flag_char;
// 跳过4字节ip,读取随后字节判断是否为标志字节
flag_char=data[offset+4];
if(flag_char == REDIRECT_MODE_1) {
// 读取国家偏移(3个字节)
ulong countryOffset=getInt32(&data[offset+5],3);
// 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向
flag_char=data[countryOffset];
if(flag_char == REDIRECT_MODE_2) {
// 读取国家偏移
int temp;
temp=getInt32(&data[countryOffset+1],3);
readString(temp,loc.country);
} else
readString(countryOffset,loc.country);
// 读取地区标志
readArea(countryOffset+4,loc.area);
} else if(flag_char == REDIRECT_MODE_2) {
ulong countryOffset=getInt32(&data[offset+5],3);
readString(countryOffset,loc.country);
readArea(offset + 8,loc.area);
} else {
readString(offset+4,loc.country) ;
readArea(offset+4+strlen(loc.country)+1,loc.area);
}
return loc;
}
// 功能:从offset偏移开始解析后面的字节,读出一个地区名
// 参数:offset 地区记录的起始偏移
// 返回值:0 成功 , 1 失败
int readArea(ulong offset,byte* buf)
{
byte flag_char;
flag_char=data[offset];
if(flag_char== REDIRECT_MODE_1 || flag_char == REDIRECT_MODE_2) {
ulong areaOffset=getInt32(&data[offset+1],3);
readString(areaOffset,buf);
} else
{
readString(offset,buf);
}
return 0;
}
// 功能:从offset偏移处读取一个以0结束的字符串至buf中
// 参数: offset 字符串起始偏移
// 返回值:0 成功 1 失败
int readString(ulong offset,byte* buf)
{
int i;
buf[0]=data[offset];
for(i = 0; buf[i] != 0;)
{
i++;
offset++;
buf[i] = data[offset];
}
if(i != 0)
return 0;
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -