纯真IP数据库是一种常用的IP地址归属地查询工具,以下是纯真IP数据库格式的详解:
- 下载纯真IP数据库
在纯真IP数据库官网(http://www.cz88.net/)上下载最新版的IP数据库,通常包括两个文件:QQWry.dat
和QQWry.idx
。
- IP数据库格式
纯真IP数据库采用的是固定长度的数据格式,每条记录的长度为7个字节,格式如下:
| 4字节起始IP地址 | 3字节指向地址的偏移量 |
其中,起始IP地址和指向地址的偏移量都是无符号整数,采用小端字节序存储。
- 解析IP地址
要查询一个IP地址的归属地,需要先将IP地址转换成无符号整数,然后在IP数据库中查找对应的记录。具体步骤如下:
- 将IP地址转换成无符号整数,例如将
192.168.1.1
转换成整数3232235777
。 - 读取IP数据库文件头部的4个字节,得到IP数据库的起始IP地址和结束IP地址。
- 使用二分查找算法,在IP数据库中查找包含目标IP地址的记录。
- 读取记录中的指向地址的偏移量,根据偏移量读取指向地址的记录。
- 读取记录中的国家和地区信息,即为目标IP地址的归属地。
示例1:使用Python实现纯真IP数据库的查询功能。
import struct
def ip2int(ip):
return struct.unpack('!I', socket.inet_aton(ip))[0]
def search_ip(ip):
with open('QQWry.dat', 'rb') as f:
start, end = struct.unpack('II', f.read(8))
ip = ip2int(ip)
while start <= end:
mid = (start + end) // 2
f.seek(mid * 7 + 4)
mid_ip, offset = struct.unpack('I3xI', f.read(7))
if ip < mid_ip:
end = mid - 1
elif ip > mid_ip:
start = mid + 1
else:
f.seek(offset + 4)
data = []
c = f.read(1)
while c != b'\x00':
data.append(c)
c = f.read(1)
country = b''.join(data).decode('gbk')
f.seek(offset + 5 + len(country))
data = []
c = f.read(1)
while c != b'\x00':
data.append(c)
c = f.read(1)
area = b''.join(data).decode('gbk')
return country, area
return None, None
if __name__ == '__main__':
country, area = search_ip('202.204.80.112')
print(country, area)
在上面的代码中,我们使用Python实现了纯真IP数据库的查询功能。首先,我们定义了一个ip2int()
函数,用于将IP地址转换成无符号整数。然后,我们打开IP数据库文件,读取文件头部的4个字节,得到IP数据库的起始IP地址和结束IP地址。接着,我们使用二分查找算法,在IP数据库中查找包含目标IP地址的记录。如果找到了目标IP地址的记录,我们就读取记录中的国家和地区信息,即为目标IP地址的归属地。
示例2:使用C语言实现纯真IP数据库的查询功能。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <arpa/inet.h>
typedef struct {
uint32_t start_ip;
uint32_t end_ip;
uint32_t offset;
} Record;
uint32_t ip2int(char *ip) {
struct in_addr addr;
inet_aton(ip, &addr);
return ntohl(addr.s_addr);
}
void search_ip(char *ip, char *filename) {
FILE *fp = fopen(filename, "rb");
if (fp == NULL) {
printf("Failed to open file %s\n", filename);
return;
}
uint32_t start, end;
fread(&start, sizeof(uint32_t), 1, fp);
fread(&end, sizeof(uint32_t), 1, fp);
uint32_t target_ip = ip2int(ip);
while (start <= end) {
uint32_t mid = (start + end) / 2;
fseek(fp, mid * sizeof(Record) + 8, SEEK_SET);
Record record;
fread(&record, sizeof(Record), 1, fp);
if (target_ip < record.start_ip) {
end = mid - 1;
} else if (target_ip > record.end_ip) {
start = mid + 1;
} else {
fseek(fp, record.offset + 4, SEEK_SET);
char buf[256];
fread(buf, 1, 256, fp);
char *country = buf;
char *area = strchr(country, '\0') + 1;
printf("%s %s\n", country, area);
return;
}
}
printf("Not found\n");
fclose(fp);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage: %s <ip> <filename>\n", argv[0]);
return 1;
}
search_ip(argv[1], argv[2]);
return 0;
}
在上面的代码中,我们使用C语言实现了纯真IP数据库的查询功能。首先,我们定义了一个ip2int()
函数,用于将IP地址转换成无符号整数。然后,我们打开IP数据库文件,读取文件头部的4个字节,得到IP数据库的起始IP地址和结束IP地址。接着,我们使用二分查找算法,在IP数据库中查找包含目标IP地址的记录。如果找到了目标IP地址的记录,我们就读取记录中的国家和地区信息,即为目标IP地址的归属地。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:纯真ip数据库格式详解 - Python技术站