使用 GeoIP2 获取 IP 的地理位置

1. 准备工做git

准备好这两个就能够了。github


 2. 敲代码数据库

我使用的操做系统是 CentOS7.1。bootstrap

2.1 编译 libmaxminddb
把 libmaxminddb 的代码下载下来,随便放在什么地方, 而后解压,进入解压后的目录,执行 bootstrap,configure,make服务器

$ tar xzf libmaxminddb-1.3.1.tar.gz $ cd libmaxminddb-1.3.1 $ ./bootstrap $ ./configure $ make

1.在执行 bootstrap 的时候可能会报错,应该是缺乏 autoconf 之类的自动构建工具致使的,到谷歌或者百度查询一下安装便可。ide

2.在执行 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.工具

既然是测试使用的,那么不编译应该也没什么大问题。测试

3.看 make 命令后的编译记录,能够发现 libmaxminddb.a 静态连接库已经编译好了, 而且放在了 libmaxminddb-1.3.1/src/.libs 目录里面。ui

[root@fengbo libmaxminddb-1.3.1]# ls src/.libs/ -l total 312
-rw-r--r--. 1 root root  12632 Dec  8 22:30 data-pool.o -rw-r--r--. 1 root root 111620 Dec  8 22:30 libmaxminddb.a lrwxrwxrwx. 1 root root     18 Dec  8 22:30 libmaxminddb.la -> ../libmaxminddb.la -rw-r--r--. 1 root root    959 Dec  8 22:30 libmaxminddb.lai lrwxrwxrwx. 1 root root     21 Dec  8 22:30 libmaxminddb.so -> libmaxminddb.so.0.0.7 lrwxrwxrwx. 1 root root     21 Dec  8 22:30 libmaxminddb.so.0 -> libmaxminddb.so.0.0.7
-rwxr-xr-x. 1 root root  79477 Dec  8 22:30 libmaxminddb.so.0.0.7
-rw-r--r--. 1 root root 100104 Dec  8 22:30 maxminddb.o

2.2 编写示例代码this

示例代码是从 maxmind 的官方 GitHub 上直接复制下来的。不过我加了几条日志信息。 https://github.com/maxmind/libmaxminddb/blob/master/doc/libmaxminddb.md#example

代码以下:$cat 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);
}
View Code

编译咱们的示例代码:

把 libmaxminddb 源码中的 libmaxminddb-1.3.1/include/maxminddb_config.h 和 libmaxminddb-1.3.1/include/maxminddb.h 放到 example.c 所在的目录下。 还有 libmaxminddb-1.3.1/src/.libs/libmaxminddb.a 也要放进来。

$ gcc -o example example.c ./libmaxminddb.a $ ls example example.c libmaxminddb.a maxminddb_config.h maxminddb.h

2.3 下载 GeoLite2 开源数据库
到网页 https://dev.maxmind.com/geoip/geoip2/geolite2/ 中,下载 GeoLite2 的数据库。

Downloads

Database MaxMind DB binary, gzipped CSV format, zipped
GeoLite2 City Download (md5 checksum) Download (md5 checksum)
GeoLite2 Country Download (md5 checksum) Download (md5 checksum)
GeoLite2 ASN (Autonomous System Number) Download (md5 checksum) Download (md5 checksum)

我下载的是 GeoLite2 City 数据库。解压后的文件以下:

[root@fengbo maxmind]# ls GeoLite2-City_20171205/ COPYRIGHT.txt GeoLite2-City.mmdb  LICENSE.txt  README.txt

2.4 测试一下这个程序的效果
先拿到一个 IP,好比 www.fengbohello.top 的 IP。

[root@fengbo maxmind]$ ping www.fengbohello.top PING www.fengbohello.top (139.199.212.133) 56(84) bytes of data. 64 bytes from 139.199.212.133: icmp_seq=1 ttl=48 time=41.7 ms

运行一下 example 试试看:

[root@fengbo maxmind]$ ./example GeoLite2-City_20171205/GeoLite2-City.mmdb "139.199.212.133" { "city": { "geoname_id": 1816670 <uint32>
        "names": { "de": "Peking" <utf8_string>
            "en": "Beijing" <utf8_string>
            "es": "Pekín" <utf8_string>
            "fr": "Pékin" <utf8_string>
            "ja": "北京市" <utf8_string>
            "pt-BR": "Pequim" <utf8_string>
            "ru": "Пекин" <utf8_string>
            "zh-CN": "北京" <utf8_string> } } "continent": { "code": "AS" <utf8_string>
        "geoname_id": 6255147 <uint32>
        "names": { "de": "Asien" <utf8_string>
            "en": "Asia" <utf8_string>
            "es": "Asia" <utf8_string>
            "fr": "Asie" <utf8_string>
            "ja": "アジア" <utf8_string>
            "pt-BR": "Ásia" <utf8_string>
            "ru": "Азия" <utf8_string>
            "zh-CN": "亚洲" <utf8_string> } } "country": { "geoname_id": 1814991 <uint32>
        "iso_code": "CN" <utf8_string>
        "names": { "de": "China" <utf8_string>
            "en": "China" <utf8_string>
            "es": "China" <utf8_string>
            "fr": "Chine" <utf8_string>
            "ja": "中国" <utf8_string>
            "pt-BR": "China" <utf8_string>
            "ru": "Китай" <utf8_string>
            "zh-CN": "中国" <utf8_string> } } "location": { "accuracy_radius": 50 <uint16>
        "latitude": 39.928900 <double>
        "longitude": 116.388300 <double>
        "time_zone": "Asia/Shanghai" <utf8_string> } "registered_country": { "geoname_id": 1814991 <uint32>
        "iso_code": "CN" <utf8_string>
        "names": { "de": "China" <utf8_string>
            "en": "China" <utf8_string>
            "es": "China" <utf8_string>
            "fr": "Chine" <utf8_string>
            "ja": "中国" <utf8_string>
            "pt-BR": "China" <utf8_string>
            "ru": "Китай" <utf8_string>
            "zh-CN": "中国" <utf8_string> } } "subdivisions": [ { "geoname_id": 2038349 <uint32>
          "iso_code": "11" <utf8_string>
          "names": { "en": "Beijing" <utf8_string>
              "fr": "Municipalité de Pékin" <utf8_string>
              "zh-CN": "北京市" <utf8_string> } } ] }
View Code

我擦,解析结果竟然是北京。我问了十三哥,他说咱们的服务器是腾讯云的,当时选择的是深圳机房。

下面是使用不一样的厂商获得的结果:

厂商 地理位置
百度 广东省广州市 腾讯集团
ip.cn 广东省深圳市 腾讯云
freegeoip.net China.Beijing
新浪:int.dpool.sina.com.cn 中国.广东.广州
淘宝:ip.taobao.com 中国.华南.广东省.广州市.电信
腾讯:ip.qq.com 中国广东省广州市 未知

有意思吧,我也不知道该信谁的。


同步发表:https://www.fengbohello.top/archives/ip2location-geolite2

相关文章
相关标签/搜索