IP地址库使用整理(Linux C)

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. 引入库流程

  1. 将库文件放到指定lib下并在Makefile中添加-lmaxminddb
  2. 将头文件maxminddb_config.h和maxminddb.h放到对应include下
  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值