?? 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 + -