在 .NET 项目中使用 IP2Region 获取 IP 地址信息

xieshuoshuo 发布于 2025-04-02 658 次阅读 预计阅读时间: 4 分钟


在现代的 Web 应用中,记录用户登录的 IP 地址是一项常见需求。然而,仅仅记录 IP 地址在日志中,对于运维人员来说并不友好,因为很难一眼看出 IP 地址对应的地理位置。因此,在项目中引入 IP 地址定位功能变得尤为重要。在线 API 接口虽然方便,但通常有调用次数限制且不支持商用。为此,我们选择了开源的离线 IP 地址定位库——IP2Region。

IP2Region 是什么?

IP2Region 是一个高效的离线 IP 地址定位库,具备 10 微秒级别的查询效率。它支持多种主流编程语言,并提供了 xdb 数据生成和查询客户端的实现。

Ip2Region技术选型优势

核心特性对比

方案类型查询延迟数据隐私商用成本扩展性
在线API100-500ms依赖第三方
Ip2Region10-20μs免费支持自定义字段

架构亮点解析

  1. xdb数据引擎
  • 二进制压缩格式(11MB基础库)
  • 支持国家|区域|省份|城市|ISP五级地理信息
  • 允许追加GPS坐标等扩展字段
  1. 多级缓存策略

IP2Region 的特性

  1. IP 数据管理框架
  • 支持亿级别的 IP 数据段行数。
  • 默认的 region 信息格式为 国家|区域|省份|城市|ISP,支持自定义。
  1. 数据去重和压缩
  • xdb 格式生成程序会自动去重和压缩数据。
  • 默认的 IP 数据生成的 ip2region.xdb 数据库文件大小为 11MiB。
  1. 极速查询响应
  • 单次查询响应时间在十微秒级别。
  • 可以通过内存加速查询,包括 vIndex 索引缓存和整个 xdb 文件缓存。

如何在 .NET 项目中使用 IP2Region

  1. 安装 NuGet 包
    使用 NuGet 包管理器安装 IP2Region.Net 包。可以通过 NuGet 包管理器界面搜索 IP2Region.Net,或者直接在包管理器控制台执行以下命令:
   Install-Package IP2Region.Net
  1. 引入依赖项
    在代码文件中引入必要的命名空间:
   using IP2Region.Net.Abstractions;
   using IP2Region.Net.XDB;
  1. 下载 xdb 文件
    从 IP2Region 的 GitHub 页面下载 ip2region.xdb 文件,并保存到项目的合适位置。你可以从以下链接下载:
  1. 使用 IP2Region 查询 IP 地址信息
    使用以下代码初始化 Searcher 并查询 IP 地址信息(项目目录):
   ISearcher searcher = new Searcher(new CachePolicy(), Environment.CurrentDirectory + @"\\ip2region.xdb");
   String ipinfo = searcher.Search(ip);
   Console.WriteLine(ipinfo);

如果 ip2region.xdb 文件存放在指定文件夹内,例如 D 盘根目录,可以修改路径:

   ISearcher searcher = new Searcher(new CachePolicy(), "D:\\ip2region.xdb");
   String ipinfo = searcher.Search(ip);
   Console.WriteLine(ipinfo);
  1. 处理查询结果
    IP2Region 返回的 IP 地址信息格式为 国家|区域|省份|城市|网络。例如,查询阿里云 IP 地址可能会返回 中国|0|浙江省|杭州市|阿里云。此外,IP2Region 还能识别内网地址,如 ::1127.0.0.1localhost 等。
  2. 参考代码示例
   using IP2Region.Net.XDB;
   private string GetLocation(string ip)
   {
       try
       {
           ISearcher searcher = new Searcher(new CachePolicy(), Environment.CurrentDirectory + @"\\ip2region.xdb");
           String ipinfo = searcher.Search(ip);
           return string.IsNullOrEmpty(ipinfo) ? "未知位置" : ipinfo;
       }
       catch (Exception ex)
       {
           return $"IP查询失败: {ex.Message}";
       }
   }