获取默认网关

Fre*_*oot 26 c# network-programming network-protocols

我正在编写一个程序,向用户显示他们的IP地址,子网掩码和默认网关.我可以得到前两个,但对于最后一个,这就是我出现的:

GatewayIPAddressInformationCollection gwc = 
    System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].GetIPProperties().GatewayAddresses;
Run Code Online (Sandbox Code Playgroud)

当然,这会返回一个集合GatewayIPAddressInformation.因此,如果计算机有多个网关,我如何确定哪个是默认网关?

在实践中,我只看到过这个集合包含一个条目,但由于它是作为集合实现的,因此有些计算机包含多个网关,其中没有一个被标记为"默认".那么有没有办法确定默认值还是只是猜测?

cae*_*say 38

它应该是第一个启用的网络接口的第一个有效和启用的网关地址:

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();
}
Run Code Online (Sandbox Code Playgroud)

我还添加了一些进一步评论的检查,这些检查已经被其他人指出是有用的.您可以检查AddressFamily一个区分IPv4和IPv6.如果您在0.0.0.0返回地址时遇到问题,可以使用后者.

也就是说,推荐的方法是使用它GetBestInterface来查找路由到特定IP地址的接口.如果您已经考虑了目标IP地址,那么最好使用它 - 所以我还包括以下示例:

[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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我可能不是第一个.在我的测试中,第一个已被禁用,因此第二个是正确的.所以在LINQ语句中添加一个条件:Where(o => o.OperationalStatus == OperationalStatus.Up) (6认同)