使用 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

相關文章
相關標籤/搜索