首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 實作 IP 區段查詢:高效率 IP 範圍比對與地理定位

     編輯:關於C語言

前言

在網路應用中,常需根據 IP 位址判斷所屬區段(如城市、ISP、公司內部網段)。本文提供完整 C# 實作,核心在於將 IPv4 位址轉換為 ulong 整數,透過數值區間比對快速定位,適用於 IP 地理資訊、存取控制、流量分析等場景。

核心原理:IPv4 轉換為無號長整數

IPv4 位址為 32 位元(4 位元組),例如 219.148.24.0。將其視為大端序(Big-Endian)無號整數:

219 × 256³ + 148 × 256² + 24 × 256¹ + 0 × 256⁰ = 3,681,203,200

轉換演算法:

public static ulong IP2A(string ip)
{
    byte[] bytes = IPAddress.Parse(ip).GetAddressBytes(); // 取得 4 位元組
    ulong ret = 0;
    foreach (byte b in bytes)
    {
        ret <<= 8;   // 左移 8 位(乘 256)
        ret |= b;    // 加上目前位元組
    }
    return ret;
}

關鍵細節:IPAddress.Address 屬性回傳的是有號長整數(可能為負),且位元組序可能不同,不可直接使用,必須自行轉換。

類別設計

IPRange:單一 IP 區段

public class IPRange
{
    public string Name { get; set; }      // 區段名稱(如「石家莊」)
    public ulong BeginIP { get; set; }    // 起始 IP(數值)
    public ulong EndIP { get; set; }      // 結束 IP(數值)
    
    public ulong Range => EndIP - BeginIP; // 區段大小
    
    public IPRange(string name, string ipBegin, string ipEnd)
    {
        Name = name;
        BeginIP = IP2A(ipBegin);
        EndIP = IP2A(ipEnd);
    }
    
    // 靜態比較器:依區段大小排序(大區段優先或依需求調整)
    public static int Compare(IPRange x, IPRange y)
    {
        if (x.Range == y.Range) return 0;
        return x.Range > y.Range ? 1 : -1;
    }
}

IPRangeManage:區段集合管理與查詢

public class IPRangeManage
{
    private List _list = new List();
    private bool _needSort = true;
    
    public void Add(IPRange range)
    {
        _list.Add(range);
        _needSort = true; // 標記需重新排序
    }
    
    private void Sort()
    {
        if (_needSort)
        {
            _list.Sort(IPRange.Compare);
            _needSort = false;
        }
    }
    
    public IPRange Search(string ipString)
    {
        ulong ip = IPRange.IP2A(ipString);
        Sort(); // 確保已排序
        
        foreach (var range in _list)
        {
            if (range.BeginIP <= ip && range.EndIP >= ip)
                return range; // 找到符合區段
        }
        return null; // 無匹配
    }
}

使用範例

static void Main()
{
    var manager = new IPRangeManage();
    
    // 新增區段(名稱、起始IP、結束IP)
    manager.Add(new IPRange("石家莊", "219.148.24.0", "219.148.63.255"));
    manager.Add(new IPRange("石家莊", "222.222.0.0", "222.222.63.255"));
    manager.Add(new IPRange("唐山", "219.148.64.0", "219.148.79.255"));
    manager.Add(new IPRange("保定", "219.148.20.0", "219.148.23.255"));
    
    // 查詢
    var result = manager.Search("219.148.56.3");
    Console.WriteLine(result?.Name ?? "未找到"); // 輸出:石家莊
}

效能與擴展建議

  • 二分搜尋:區段量大(>1萬筆)時,將 foreach 改為二分搜尋,複雜度從 O(n) 降為 O(log n)
  • IPv6 支援:改用 System.Numerics.BigInteger(128 位元)儲存 IPv6
  • 資料來源:可從 CSV、資料庫、API 載入區段資料,啟動時建立索引
  • 執行緒安全:多執行緒環境下加鎖或使用 ImmutableList

總結

將 IP 位址轉為數值進行區間比對,是高效率 IP 定位的核心技巧。本文提供的 IPRange 與 IPRangeManage 類別結構清晰、易於擴展,可直接整合至專案中使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved