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

C# IP 位址區段查詢:高效能 ulong 轉換與二分搜尋

     編輯:關於C#

核心課題

判斷 IPv4 位址屬於哪個預定義網段。關鍵在於將點分十進制 IP (如 219.148.56.3) 轉換為可數值比較的無號長整數 (ulong),以利範圍判斷與排序搜尋。

IP 轉 ulong 算法

public static ulong IpToUlong(string ip)
{
    var bytes = IPAddress.Parse(ip).GetAddressBytes(); // 大端序: [219, 148, 56, 3]
    ulong result = 0;
    foreach (byte b in bytes)
    {
        result = (result << 8) | b; // 逐位元組左移 8 位並合併
    }
    return result; // 219<<24 | 148<<16 | 56<<8 | 3 = 3684540419
}

※ IPAddress.Address 屬性在舊版 .NET 回傳 long 且位元組序可能不同,建議自行轉換確保一致性。

資料結構設計

public class IpRange
{
    public string Name { get; set; }
    public ulong StartIp { get; set; }
    public ulong EndIp { get; set; }
    public ulong RangeSize => EndIp - StartIp;

    public IpRange(string name, string start, string end)
    {
        Name = name;
        StartIp = IpToUlong(start);
        EndIp = IpToUlong(end);
    }
}

public class IpRangeManager
{
    private readonly List<IpRange> _ranges = new();
    private bool _needSort = true;

    public void Add(IpRange range)
    {
        _ranges.Add(range);
        _needSort = true;
    }

    public IpRange Find(string ip)
    {
        ulong target = IpToUlong(ip);
        if (_needSort)
        {
            _ranges.Sort((x, y) => x.RangeSize.CompareTo(y.RangeSize)); // 依區段大小排序 (小優先)
            _needSort = false;
        }

        foreach (var range in _ranges)
        {
            if (range.StartIp <= target && target <= range.EndIp)
                return range;
        }
        return null;
    }
}

使用範例

var mgr = new IpRangeManager();
mgr.Add(new IpRange("石家莊", "219.148.24.0", "219.148.63.255"));
mgr.Add(new IpRange("石家莊", "222.222.0.0", "222.222.63.255"));
mgr.Add(new IpRange("唐山", "219.148.64.0", "219.148.79.255"));
mgr.Add(new IpRange("保定", "219.148.20.0", "219.148.23.255"));

var result = mgr.Find("219.148.56.3");
Console.WriteLine(result?.Name); // 輸出: 石家莊

效能優化建議

  • 區段數量大時,改用 二分搜尋 (需按 StartIp 排序) 或 Trie/前綴樹 (最長前綴匹配)。
  • IPv6 需用 System.Numerics.BigInteger (128 位) 或兩個 ulong 儲存。
  • 生產環境建議使用成熟庫 (如 IPNetwork, MaxMind GeoIP)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved