これはおそらく、最初に有効になったネットワーク インターフェイスの最初の有効で有効なゲートウェイ アドレスになります。
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;
}
これらの 2 つの例は、ヘルパー クラスにまとめて、適切な場合に使用することができます。つまり、宛先アドレスをまだ考えていない場合です。