它可能是第一个启用的网络接口的第一个有效且启用的网关地址:
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();
}
我还添加了一些进一步的注释检查,其他人在这里指出这些检查很有用。您可以检查其中AddressFamily
一项以区分 IPv4 和 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;
}
这两个示例可以封装到一个辅助类中并在适当的情况下使用:您有,或者您还没有记住目标地址。