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

C# IP 路由判斷實作:子網遮罩與網路位址比對演算法

     編輯:關於C#

路由判斷核心邏輯

給定 **目標 IP**、**路由器子網遮罩**、**路由器網路位址**。
判斷:`(目標 IP AND 子網遮罩) == 路由器網路位址` → 可經由該路由轉發。

位元運算實作


public static class RoutingHelper
{
    /// 
    /// 判斷目標 IP 是否落在路由器網段內
    /// 
    public static bool CanRoute(string targetIp, string subnetMask, string networkAddress)
    {
        var tip = ParseIp(targetIp);
        var mask = ParseIp(subnetMask);
        var net = ParseIp(networkAddress);

        for (int i = 0; i < 4; i++)
        {
            if ((tip[i] & mask[i]) != net[i])
                return false;
        }
        return true;
    }

    private static byte[] ParseIp(string ip)
    {
        var parts = ip.Split('.');
        if (parts.Length != 4) throw new ArgumentException("IP 格式錯誤");
        var bytes = new byte[4];
        for (int i = 0; i < 4; i++)
            bytes[i] = byte.Parse(parts[i]);
        return bytes;
    }
}

// 使用範例
// 目標: 130.50.15.9
// 路由器: 255.255.252.0 / 130.50.15.0
// 130.50.15.9 & 255.255.252.0 = 130.50.12.0 != 130.50.15.0 → 不可路由
bool ok = RoutingHelper.CanRoute("130.50.15.9", "255.255.252.0", "130.50.15.0"); // false

CIDR 表示法支援 (現代標準)


public static bool CanRouteCIDR(string targetIp, string cidr) // e.g. "130.50.12.0/22"
{
    var parts = cidr.Split('/');
    var netAddr = ParseIp(parts[0]);
    int prefixLen = int.Parse(parts[1]);

    // 建立遮罩
    var mask = new byte[4];
    for (int i = 0; i < prefixLen; i++)
        mask[i / 8] |= (byte)(0x80 >> (i % 8));

    var tip = ParseIp(targetIp);
    for (int i = 0; i < 4; i++)
        if ((tip[i] & mask[i]) != netAddr[i]) return false;
    return true;
}

完整路由表查找 (最長前綴匹配)


public class Router
{
    private readonly List _routes = new();

    public void AddRoute(string networkCidr, string nextHop, string interfaceName)
    {
        _routes.Add(new RouteEntry(networkCidr, nextHop, interfaceName));
    }

    public RouteEntry Lookup(string targetIp)
    {
        // 最長前綴匹配:先按前綴長度降序排序
        return _routes
            .OrderByDescending(r => r.PrefixLength)
            .FirstOrDefault(r => r.Match(targetIp));
    }
}

public class RouteEntry
{
    public byte[] Network { get; }
    public byte[] Mask { get; }
    public int PrefixLength { get; }
    public string NextHop { get; }
    public string Interface { get; }

    public RouteEntry(string cidr, string nextHop, string iface)
    {
        var parts = cidr.Split('/');
        Network = ParseIp(parts[0]);
        PrefixLength = int.Parse(parts[1]);
        NextHop = nextHop;
        Interface = iface;

        Mask = new byte[4];
        for (int i = 0; i < PrefixLength; i++)
            Mask[i / 8] |= (byte)(0x80 >> (i % 8));
    }

    public bool Match(string targetIp)
    {
        var tip = ParseIp(targetIp);
        for (int i = 0; i < 4; i++)
            if ((tip[i] & Mask[i]) != Network[i]) return false;
        return true;
    }
}

IPv6 擴充提示

  • 使用 `IPAddress` / `System.Net.Primitives` 內建 `MapToIPv6`、`GetAddressBytes` (16 bytes)。
  • 遮罩同樣為 128 位元前綴長度。
  • 建議直接使用 `System.Net.IPNetwork` (第三方) 或 .NET 7+ `IPNetwork.Parse`。

總結

路由判斷本質是 **位元級 AND 運算 + 比較**。掌握 `byte[]` 解析、CIDR 遮罩生成、**最長前綴匹配 (LPM)** 排序查找,即可實作完整路由表查詢邏輯。生產級路由器仍建議使用 **BPF / eBPF / DPDK / P4** 等資料平面技術以達到線速轉發。

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