判斷 IPv4 位址屬於哪個預定義網段。關鍵在於將點分十進制 IP (如 219.148.56.3) 轉換為可數值比較的無號長整數 (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/前綴樹 (最長前綴匹配)。System.Numerics.BigInteger (128 位) 或兩個 ulong 儲存。IPNetwork, MaxMind GeoIP)。