⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myipshow.c

📁 纯真IP数据库
💻 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 + -