Linux C 使用 libmaxminddb 读取 GeoIP2 MMDB 获取 IP 的地理位置
0 运行环境
-
Ubuntu 18 x64
-
libmaxminddb 1.4.3
1 准备工作
-
数据库 : 解析 IP 地理位置的数据库来自 maxmind 官网的 GeoIP2 开源数据库:https://dev.maxmind.com/geoip/geoip2/geolite2/
-
C 语言 API : 使用的 API 是 maxmind 官网的开源项目 libmaxminddb,地址是 https://github.com/maxmind/libmaxminddb
2 编译 libmaxminddb
2.1 克隆 libmaxminddb
$ git clone --recursive https://github.com/maxmind/libmaxminddb
2.2 执行 bootstrap
$ cd libmaxminddb-1.3.1
$ ./bootstrap
在执行 bootstrap 的时候可能会报错,如下所示:
./bootstrap: 7: ./bootstrap: autoreconf: not found
原因 linux 系统缺少 autoreconf 工具
2.2.1 安装 autoreconf 工具
sudo apt-get install autoconf automake libtool
2.2.2 重新执行 bootstrap
2.3 执行 configure
$ ./configure
2.4 执行 make
$ make
看 make 命令后的编译记录,可以发现 libmaxminddb.a 静态链接库已经编译好了, 并且放在了 libmaxminddb/src/.libs 目录里面。(注意该目录为隐藏目录)
ps:
ll
可以列出目录下的所有文件,包括以 . 开头的隐含文件。
2.5 查看 libmaxminddb.a 静态链接库
$ ll src/.libs
3 示例代码
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);
}
3.1 编译示例代码
把 libmaxminddb 源码中的 libmaxminddb/include/maxminddb_config.h 和 libmaxminddb/include/maxminddb.h 放到 example.c 所在的目录下。
还有 libmaxminddb/src/.libs/libmaxminddb.a 也要放进来。
然后再用 gcc 编译
$ cd libmaxminddb/include/
$ mv maxminddb_config.h /home/zyw/GeoIP2
$ mv maxminddb.h /home/zyw/GeoIP2
$ cd --
$ cd libmaxminddb/src/.libs/
$ mv libmaxminddb.a /home/zyw/GeoIP2
$ cd --
$ cd /home/zyw/GeoIP2
$ gcc -o example example.c ./libmaxminddb.a
$ ls
4 下载 GeoLite2 开源数据库
开源库下载地址:https://dev.maxmind.com/geoip/geoip2/geolite2/
从 2019年12月30日开始,要获得免费下载 GeoLite2 数据库的访问权限,需要注册一个 GeoLite2帐户。
(账号名为注册时填写的邮箱号)
点击 Download Databases 进入下载界面
我下载的是 GeoLite2 City 数据库。选择如下:
解压后的文件如下:
$ tar xzf GeoLite2-City_20201208.tar.gz
$ ls GeoLite2-City_20201208
这里提供一个我下载好的 GeoLite2-City_20201208.tar.gz:
链接:https://pan.baidu.com/s/1gLOf1u68wIt9Wj50PfUJgw
提取码:hhhh
5 测试示例代码
把 GeoLite2-City.mmdb 移动到 example.c 所在的目录下。
$ cd GeoLite2-City_20201208/
$ mv GeoLite2-City.mmdb /home/zyw/GeoIP2/
$ cd --
$ cd GeoIP2/
$ ls
$ ./example GeoLite2-City.mmdb "139.199.212.133"
运行结果:
6 参考资料
1、[记录] 安装 maxminddb 扩展 - cnguu - https://learnku.com/articles/26915
2、使用 GeoIP2 获取 IP 的地理位置 - fengbohello - https://www.cnblogs.com/fengbohello/p/8144788.html
3、libmaxminddb - https://github.com/maxmind/libmaxminddb
4、GeoLite2 开源数据库下载地址:https://dev.maxmind.com/geoip/geoip2/geolite2/
5、MaxMind DB File Format Specification:http://maxmind.github.io/MaxMind-DB/
6、libmaxminddb - 疯疯癫癫 - https://blog.csdn.net/fengfengdiandia/article/details/78278198