IP地址库资源使用整理
一、ip2region 国内资源
Ip2region为开源项目,github地址:https://github.com/lionsoul2014/ip2region。gitee地址:https://gitee.com/lionsoul/ip2region。目前最新已更新到了v2.0版本,ip2region v2.0是一个离线IP地址定位库和IP定位数据管理框架,10微秒级别的查询效率,并提供了众多主流编程语言的 xdb 数据生成和查询客户端实现。
每条ip数据段都固定了格式:
_城市Id|国家|区域|省份|城市|ISP_
1. 特点:
-
数据聚合了一些知名ip到地名查询提供商的数据,经测试着实比经典的纯真IP定位准确一些。
-
多查询客户端的支持。
-
ip2region的数据聚合自以下服务商的开放API或者数据(升级程序每秒请求次数2到4次):
2. 数据来源:
80%以上, 淘宝IP地址库, http://ip.taobao.com/ (将于2022年3月31日起永久关停)
≈10%, GeoIP, https://geoip.com/
≈2%, 纯真IP库, http://www.cz88.net
注:如果上述开放API或者数据都不给开放数据时ip2region将停止数据的更新服务,目前已经很久没更新了
3. 数据内容:
//每个 ip 数据段的 region 信息都固定了格式:
国家|区域|省份|城市|ISP
//只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,后前的选项全部是0。
4. C语言 Linux使用例子
1) 下载代码请复制以下命令到终端执行
git clone https://gitee.com/lionsoul/ip2region.git
2) 通过如下方式编译得到 xdb_searcher 可执行程序:
# cd 到 c binding 根目录
make
3) 查询测试
通过 xdb_searcher search 命令来测试对 ip2region.xdb 的查询:
命令行:
./xdb_searcher search
结果:
./xdb_searcher search [command options]
options:
--db string ip2region binary xdb file path
--cache-policy string cache policy: file/vectorIndex/content
例如:使用默认的 data/ip2region.xdb 进行查询测试:
命令行:
./xdb_searcher search --db=../../data/ip2region.xdb --cache-policy=vectorIndex
使用java生成的xdb文件
./xdb_searcher search --db=../../maker/java/ip2region.xdb --cache-policy=vectorIndex
输入 ip 即可进行查询,输入 quit 即可退出测试程序。也可以分别设置 cache-policy 为 file/vectorIndex/content 来测试三种不同的缓存实现的效率。
4) bench 测试
通过 xdb_searcher bench 命令来进行 bench 测试,一方面确保查询程序和 xdb 文件没有错误,另一方面可以通过大量的查询得到评价的查询性能:
命令行:
./xdb_searcher bench
结果:
./xdb_searcher bench [command options]
options:在这里插入代码片
--db string ip2region binary xdb file path
--src string source ip text file path
--cache-policy string cache policy: file/vectorIndex/content
例如:通过默认的 data/ip2region.xdb 和 data/ip.merge.txt 来进行 bench 测试:
命令行:
./xdb_searcher bench --db=../../data/ip2region.xdb --src=../../data/ip.merge.txt --cache-policy=vectorIndex
结果:
Bench finished, {cache_policy: vectorIndex, total: 3417955, took: 4.233s, cost: 1 μs/op}
可以设置 cache-policy 参数来分别测试 file/vectorIndex/content 不同缓存实现机制的效率。
@Note:请注意 bench 使用的 src 文件需要是生成对应的 xdb 文件相同的源文件。
5. 自测C语言例子
1) 代码:
#include "stdio.h"
#include "xdb_searcher.h"
struct searcher_test_entry {
xdb_searcher_t searcher;
xdb_vector_index_t *v_index;
xdb_content_t *c_buffer;
};
typedef struct searcher_test_entry searcher_test_t;
int init_searcher_test(searcher_test_t *test, char *db_path, char *cache_policy) {
int err;
test->v_index = NULL;
test->c_buffer = NULL;
if (strcmp(cache_policy, "file") == 0) {
err = xdb_new_with_file_only(&test->searcher, db_path);
if (err != 0) {
printf("failed to create searcher with errcode=%d\n", err);
return 1;
}
} else if (strcmp(cache_policy, "vectorIndex") == 0) {
test->v_index = xdb_load_vector_index_from_file(db_path);
if (test->v_index == NULL) {
printf("failed to load vector index from `%s`\n", db_path);
return 2;
}
err = xdb_new_with_vector_index(&test->searcher, db_path, test->v_index);
if (err != 0) {
printf("failed to create vector index cached searcher with errcode=%d\n", err);
return 3;
}
} else if (strcmp(cache_policy, "content") == 0) {
test->c_buffer = xdb_load_content_from_file(db_path);
if (test->c_buffer == NULL) {
printf("failed to load xdb content from `%s`\n", db_path);
return 4;
}
err = xdb_new_with_buffer(&test->searcher, test->c_buffer);
if (err != 0) {
printf("failed to create content cached searcher with errcode=%d\n", err);
return 5;
}
} else {
printf("invalid cache policy `%s`, options: file/vectorIndex/content\n", cache_policy);
return 6;
}
return 0;
}
void destroy_searcher_test(searcher_test_t *test) {
xdb_close(&test->searcher);
// check and free the vector index
if (test->v_index != NULL) {
xdb_close_vector_index(test->v_index);
test->v_index = NULL;
}
// check and free the content buffer
if (test->c_buffer != NULL) {
xdb_close_content(test->c_buffer);
test->c_buffer = NULL;
}
}
//read a line from a command line.
static char *get_line(FILE *fp, char *__dst) {
register int c;
register char *cs;
cs = __dst;
while ( ( c = getc( fp ) ) != EOF ) {
if ( c == '\n' ) break;
*cs++ = c;
}
*cs = '\0';
return ( c == EOF && cs == __dst ) ? NULL : __dst;
}
void test_search(char *ip_address) {
int err;
// Default parameters
char db_file[] = "../../data/ip2region.xdb";
char cache_policy[] = "vectorIndex";
// Initialize searcher
searcher_test_t test;
err = init_searcher_test(&test, db_file, cache_policy);
if (err != 0) {
// 初始化程序会打印错误原因
return;
}
char region[512] = {'\0'};
unsigned int ip;
// 将 IP 地址转换为整数
if (xdb_check_ip(ip_address, &ip) != 0) {
printf("Invalid IP address: %s\n", ip_address);
destroy_searcher_test(&test);
return;
}
// 查询地理位置信息
err = xdb_search(&test.searcher, ip, region, sizeof(region));
if (err != 0) {
printf("{err: %d, io_count: %d}\n", err, xdb_get_io_count(&test.searcher));
} else {
printf("{region: %s, io_count: %d}\n", region, xdb_get_io_count(&test.searcher));
// 如果查询结果中包含 "中国" 字样,则为国内 IP,否则为国外 IP
if (strstr(region, "中国") != NULL) {
printf("IP 地址 %s 是国内 IP\n", ip_address);
} else {
printf("IP 地址 %s 是国外 IP\n", ip_address);
}
}
// 销毁搜索器资源
destroy_searcher_test(&test);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <ip_address>\n", argv[0]);
return 1;
}
char *ip_address = argv[1];
test_search(ip_address);
return 0;
}
2) 编译:
编译路径下有对应文件xdb_searcher.c及xdb_searcher.h
cd ip2region/binding/c
gcc -O2 -I./ xdb_searcher.c test.c -o test
3) 运行命令及结果:
./test 1.2.3.4
{region: 美国|0|华盛顿|0|谷歌, io_count: 7}
IP 地址 1.2.3.4 是国外 IP
6. 引入库流程
1) 引入xdb_searcher.c及xdb_searcher.h文件
2) 实现加头文件xdb_searcher.h
二、ip2location 国外资源
库名称:IP2Location LITE
IP2Location 包含商用版和免费版本两种,IP2Location™ LITE 为免费版本,官方地址:https://lite.ip2location.com
IP2Location™ LITE数据库由IP地址组成,这些IP地址用于确定IP地址的地理位置信息,例如国家,地区或州,城市,纬度,经度,邮政编码和时区。它支持所有IP地址,包括IPv4和IPv6。
1. 特点:
-
国外地理位置较为精确
-
每月更新
-
包含信息丰富,可选择需要的信息丰富程度的文件进行下载和处理。
-
包含IPV6地址库
2. 流程:
1) 访问地址:https://lite.ip2location.com 选择产品
2) 选择使用的库:(本图选择最全的库)
3) 选择不同语言的库:
4) 下载压缩包或者源码:
Readme及源码:
https://www.ip2location.com/development-libraries/ip2location/c
3. C语言使用例子
1) 下载压缩包后解压
2) 进入目录
cd IP2Location-C-Library-master
3) 运行以下命令
编译安装:
autoreconf -i -v --force
./configure
make
make install
生成xdb文件:
cd data
perl ip-country.pl
测试:读取country_test_ipv6_data.txt内容并查询,对比返回的国家信息与预期的是否相符
cd test
./test-IP2Location
4. 自测C语言例子
1) 代码:
#include <stdio.h>
#include <IP2Location.h>
int main() {
// 打开IP2Location数据库文件
IP2Location *IP2LocationObj = IP2Location_open("../data/IP2LOCATION-LITE-DB11.IPV6.BIN");
if (IP2LocationObj == NULL) {
printf("无法打开数据库文件\n");
return -1;
}
// 输入IP地址
char ip_address[30];
printf("请输入要查询的IP地址:");
scanf("%s", ip_address);
// 查询IP地址对应的地理位置信息
IP2LocationRecord *record = IP2Location_get_all(IP2LocationObj, ip_address);
// 输出查询结果
if (record != NULL) {
printf("IP地址:%s\n", ip_address);
printf("国家代码:%s\n", record->country_short);
printf("国家名称:%s\n", record->country_long);
printf("地区名称:%s\n", record->region);
printf("城市名称:%s\n", record->city);
printf("纬度:%f\n", record->latitude);
printf("经度:%f\n", record->longitude);
} else {
printf("无法查询到该IP地址的地理位置信息\n");
}
// 释放资源并关闭数据库文件
IP2Location_free_record(record);
IP2Location_close(IP2LocationObj);
return 0;
}
2) 编译:
gcc test.c -o test -I/usr/local/include -L/usr/local/lib -lIP2Location
3) 运行命令及结果:
./test
请输入要查询的IP地址:1.2.3.4
IP地址:1.2.3.4
国家代码:AU
国家名称:Australia
地区名称:Queensland
城市名称:Brisbane
纬度:-27.467541
经度:153.028091
5. 引入库流程
1) 引入/usr/local/include下IP2Location.h文件
2) 引入/usr/local/lib下libIP2Location.a libIP2Location.la libIP2Location.so.3.0.0文件
3) 创建软链接文件libIP2Location.so libIP2Location.so.3
4) Makefile编译选项添加库文件及头文件路径及-lIP2Location
三、geoip2
1. 准备工作
数据库 : 解析 IP 地理位置的数据库来自 maxmind 官网的 GeoIP2 开源数据库:https://dev.maxmind.com/geoip/geoip2/geolite2/
C 语言 API : 使用的 API 是 maxmind 官网的开源项目 libmaxminddb,地址是 https://github.com/maxmind/libmaxminddb
2. 编译 libmaxminddb
1) libmaxminddb
方法一:git clone --recursive https://github.com/maxmind/libmaxminddb
方法二:访问https://github.com/maxmind/libmaxminddb 下载安装包
2) 执行 bootstrap
cd libmaxminddb-main
./bootstrap
在执行 bootstrap 的时候可能会报错,如下所示:
./bootstrap: 7: ./bootstrap: autoreconf: not found
原因 linux 系统缺少 autoreconf 工具
安装 autoreconf 工具
yum install autoconf automake libtool
重新执行bootstrap
4)执行 ./configure
5) 执行make
报错信息指向的是 libmaxminddb-1.3.1/t 里面缺少 libtap/tap.h。 https://github.com/pozorvlak/libtap 是 libtap 在 GitHub 上的地址, 其项目首页上的注释是:Testing library for C, implementing the Test Anything Protocol. Written by Nik Clayton.
可以忽略问题,不影响后续测试
6) 查看 libmaxminddb.a 静态链接库
ll src/.libs
7) 示例代码 example.c
#include <errno.h>
#include "maxminddb.h"
#include <stdlib.h>
#include <string.h>
#define xdebug(fmt, arg...) \
do{\
printf("%s %d : ", __FILE__, __LINE__); \
printf(fmt, ##arg); \
printf("\n"); \
}while(0)
int main(int argc, char **argv)
{
if(argc < 2) {
xdebug("Usage : %s dbfilename IP", argv[0]);
}
char *filename = argv[1];
char *ip_address = argv[2];
MMDB_s mmdb;
int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
if (MMDB_SUCCESS != status) {
fprintf(stderr, "\n Can't open %s - %s\n",
filename, MMDB_strerror(status));
if (MMDB_IO_ERROR == status) {
fprintf(stderr, " IO error: %s\n", strerror(errno));
}
exit(1);
}
int gai_error, mmdb_error;
MMDB_lookup_result_s result =
MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error);
if (0 != gai_error) {
fprintf(stderr,
"\n Error from getaddrinfo for %s - %s\n\n",
ip_address, gai_strerror(gai_error));
exit(2);
}
if (MMDB_SUCCESS != mmdb_error) {
fprintf(stderr,
"\n Got an error from libmaxminddb: %s\n\n",
MMDB_strerror(mmdb_error));
exit(3);
}
MMDB_entry_data_list_s *entry_data_list = NULL;
int exit_code = 0;
if (result.found_entry) {
int status = MMDB_get_entry_data_list(&result.entry,
&entry_data_list);
if (MMDB_SUCCESS != status) {
fprintf(
stderr,
"Got an error looking up the entry data - %s\n",
MMDB_strerror(status));
exit_code = 4;
goto end;
}
if (NULL != entry_data_list) {
MMDB_dump_entry_data_list(stdout, entry_data_list, 2);
}
} else {
fprintf(
stderr,
"\n No entry for this IP address (%s) was found\n\n",
ip_address);
exit_code = 5;
}
end:
MMDB_free_entry_data_list(entry_data_list);
MMDB_close(&mmdb);
exit(exit_code);
}
8) 编译示例代码
把 libmaxminddb 源码中的 libmaxminddb/include/maxminddb_config.h 和 libmaxminddb/include/maxminddb.h 放到 example.c 所在的目录下。
还有 libmaxminddb/src/.libs/libmaxminddb.a 也要放进来。
然后再用 gcc 编译
mkdir test
cd test
vi example.c
cd libmaxminddb/include/
cp../include/maxminddb_config.h ./
cp../include/maxminddb.h ./
cp../src/.libs/libmaxminddb.a ./
gcc -o example example.c ./libmaxminddb.a
3. 下载 GeoLite2 开源数据库
开源库下载地址:https://dev.maxmind.com/geoip/geoip2/geolite2/
从 2019年12月30日开始,要获得免费下载 GeoLite2 数据库的访问权限,需要注册一个 GeoLite2帐户。
1)访问https://dev.maxmind.com/geoip/geoip2/geolite2/
2)注册
3)登录(账号名为注册时填写的邮箱号)
4)点击 Download Databases 进入下载界面
5)下载
6)解压
tar xzf GeoLite2-City_20240419.tar.gz
7)测试示例代码
把 GeoLite2-City.mmdb 移动到 example.c 所在的目录下。
cd libmaxminddb-main/test/
cp ../../GeoLite2-City_20240419/GeoLite2-City.mmdb ./
./example GeoLite2-City.mmdb "139.199.212.133"
4. 引入库流程
- 将库文件放到指定lib下并在Makefile中添加-lmaxminddb
- 将头文件maxminddb_config.h和maxminddb.h放到对应include下