27

ユーザーに IP アドレス、サブネット マスク、およびデフォルト ゲートウェイを表示するプログラムを作成しています。最初の 2 つは取得できますが、最後の 1 つは次のようになります。

GatewayIPAddressInformationCollection gwc = 
    System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].GetIPProperties().GatewayAddresses;

もちろん、これは のコレクションを返しますGatewayIPAddressInformation。では、コンピュータに複数のゲートウェイがある場合、どのゲートウェイがデフォルトゲートウェイかを判断するにはどうすればよいでしょうか?

実際には、このコレクションに単一のエントリが含まれているのを見たことがありませんが、コレクションとして実装されているため、一部のコンピューターに複数のゲートウェイが含まれており、いずれも「既定」としてマークされていないのは当然のことです。それで、デフォルトを決定する方法はありますか、それともすべて当て推量ですか?

4

9 に答える 9

44

これはおそらく、最初に有効になったネットワーク インターフェイスの最初の有効で有効なゲートウェイ アドレスになります。

public static IPAddress GetDefaultGateway()
{
    return NetworkInterface
        .GetAllNetworkInterfaces()
        .Where(n => n.OperationalStatus == OperationalStatus.Up)
        .Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
        .SelectMany(n => n.GetIPProperties()?.GatewayAddresses)
        .Select(g => g?.Address)
        .Where(a => a != null)
         // .Where(a => a.AddressFamily == AddressFamily.InterNetwork)
         // .Where(a => Array.FindIndex(a.GetAddressBytes(), b => b != 0) >= 0)
        .FirstOrDefault();
}

また、ここで他の人から有用であると指摘された、コメント付きのチェックをいくつか追加しました。AddressFamilyIPv4とIPv6を区別するものを確認できます。後者は、0.0.0.0 アドレスを除外するために使用できます。

上記の解決策は、有効な/接続されたインターフェイスを提供し、99% の状況で十分です。つまり、トラフィックをルーティングできる複数の有効なインターフェースがあり、100% 正確である必要がある場合、これを行う方法はGetBestInterface、特定の IP アドレスにルーティングするためのインターフェースを見つけることです。これにより、特定のアドレス範囲が別のアダプターを介してルーティングされる可能性がある場合 (たとえば10.*.*.*、VPN を介して、その他すべてがルーターに送られる) も処理されます。

[DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
private static extern int GetBestInterface(UInt32 destAddr, out UInt32 bestIfIndex);

public static IPAddress GetGatewayForDestination(IPAddress destinationAddress)
{
    UInt32 destaddr = BitConverter.ToUInt32(destinationAddress.GetAddressBytes(), 0);

    uint interfaceIndex;
    int result = GetBestInterface(destaddr, out interfaceIndex);
    if (result != 0)
        throw new Win32Exception(result);

    foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
    {
        var niprops = ni.GetIPProperties();
        if (niprops == null)
            continue;

        var gateway = niprops.GatewayAddresses?.FirstOrDefault()?.Address;
        if (gateway == null)
            continue;

        if (ni.Supports(NetworkInterfaceComponent.IPv4))
        {
            var v4props = niprops.GetIPv4Properties();
            if (v4props == null)
                continue;

            if (v4props.Index == interfaceIndex)
                return gateway;
        }

        if (ni.Supports(NetworkInterfaceComponent.IPv6))
        {
            var v6props = niprops.GetIPv6Properties();
            if (v6props == null)
                continue;

            if (v6props.Index == interfaceIndex)
                return gateway;
        }
    }

    return null;
}

これらの 2 つの例は、ヘルパー クラスにまとめて、適切な場合に使用することができます。つまり、宛先アドレスをまだ考えていない場合です。

于 2012-11-29T21:26:52.287 に答える
4

コマンドによって返される最初の IP アドレスはtracerouteゲートウェイになります。この事実を使用して、ゲートウェイを取得できますtracerout

于 2015-04-07T14:34:51.003 に答える
2

これは少し古い質問であることは知っていますが、ローカル ゲートウェイの IPV4 アドレスを取得する必要があることに気付きました。自分のシステムに関しては、受け入れられた回答は法案に完全には適合しないため、スイートに変更しました。他の人もこのソリューションを使用できると確信しています。

コメントするにはまだ十分な担当者がいないため、これを「質問」として追加せざるを得ません。

public static IPAddress GetDefaultGateway()
    {
        IPAddress result = null;
        var cards = NetworkInterface.GetAllNetworkInterfaces().ToList();
        if (cards.Any())
        {
            foreach (var card in cards)
            {
                var props = card.GetIPProperties();
                if (props == null)
                    continue;

                var gateways = props.GatewayAddresses;
                if (!gateways.Any())
                    continue;

                var gateway =
                    gateways.FirstOrDefault(g => g.Address.AddressFamily.ToString() == "InterNetwork");
                if (gateway == null)
                    continue;

                result = gateway.Address;
                break;
            };
        }

        return result;
    }
于 2015-02-16T16:35:30.307 に答える
1

私はこれに出くわしたばかりで、次のコードを使用します。基本的には、ループバックではなく、アップしていて、ゲートウェイとユニキャスト アドレスを持つインターフェイスを探します。インターフェイスから、非一時的な IPV4 アドレスを取得します。

public static class NetworkInterfaces
{
    public static NetworkInterface GetDefaultInterface()
    {
        var interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
        foreach (var intf in interfaces)
        {
            if (intf.OperationalStatus != OperationalStatus.Up)
            {
                continue;
            }
            if (intf.NetworkInterfaceType == NetworkInterfaceType.Loopback)
            {
                continue;
            }

            var properties = intf.GetIPProperties();
            if (properties == null)
            {
                continue;
            }
            var gateways = properties.GatewayAddresses;
            if ((gateways == null) || (gateways.Count == 0))
            {
                continue;
            }
            var addresses = properties.UnicastAddresses;
            if ((addresses == null) || (addresses.Count == 0))
            {
                continue;
            }
            return intf;
        }
        return null;
    }

    public static IPAddress GetDefaultIPV4Address(NetworkInterface intf)
    {
        if (intf == null)
        {
            return null;
        }
        foreach (var address in intf.GetIPProperties().UnicastAddresses)
        {
            if (address.Address.AddressFamily != AddressFamily.InterNetwork)
            {
                continue;
            }
            if (address.IsTransient)
            {
                continue;
            }
            return address.Address;
        }
        return null;
    }
}
于 2017-02-03T11:34:15.817 に答える
1
NetworkInterface[] allNICs = NetworkInterface.GetAllNetworkInterfaces();
foreach (var nic in allNICs)
{
    var ipProp = nic.GetIPProperties();
    var gwAddresses = ipProp.GatewayAddresses;
    if (gwAddresses.Count > 0 &&
        gwAddresses.FirstOrDefault(g => g.Address.AddressFamily == AddressFamily.InterNetwork) != null)
    {
        localIP = ipProp.UnicastAddresses.First(d => d.Address.AddressFamily == AddressFamily.InterNetwork).Address;
    }
}
Debug.Print(localIP.ToString());
于 2015-10-14T02:25:49.287 に答える
0

アダプターへのゲートウェイが多数ある場合、それらはすべてそのアダプターのデフォルトと見なされるため、このコレクションを反復処理してすべてのゲートウェイを表示する必要があると思います

于 2012-11-29T21:45:10.317 に答える