zoukankan      html  css  js  c++  java
  • 使用 GeoIP2 获取 IP 的地理位置

    1. 准备工作

    准备好这两个就可以了。


     2. 敲代码

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

    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 之类的自动构建工具导致的,到谷歌或者百度查询一下安装即可。

    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 目录里面。

    [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 编写示例代码

    示例代码是从 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("
    "); 
        }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, "
      Can't open %s - %s
    ",
                    filename, MMDB_strerror(status));
    
            if (MMDB_IO_ERROR == status) {
                fprintf(stderr, "    IO error: %s
    ", 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,
                    "
      Error from getaddrinfo for %s - %s
    
    ",
                    ip_address, gai_strerror(gai_error));
            exit(2);
        }
    
        if (MMDB_SUCCESS != mmdb_error) {
            fprintf(stderr,
                    "
      Got an error from libmaxminddb: %s
    
    ",
                    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
    ",
                        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,
                    "
      No entry for this IP address (%s) was found
    
    ",
                    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

    DatabaseMaxMind DB binary, gzippedCSV 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

     

  • 相关阅读:
    Android开发与Sequoyah的安装问题
    Discuz 数据库各表的作用
    jQuery-File-Upload $(...).fileupload is not a function $.widget is not a function
    phpstorm xdebug 无法断点调试问题
    Android Service 启动流程
    Discuz! 全局变量说明
    Discuz! X3 数据表、数据字段说明
    Spring Boot 搭建
    Android组件化开发(注意事项)
    NestedScrollView嵌套RecycleView发生的小问题
  • 原文地址:https://www.cnblogs.com/fengbohello/p/8144788.html
Copyright © 2011-2022 走看看