我正在写一个程序,显示用户的IP地址,子网掩码和默认网关。 我能得到前两个,但最后一个,这就是我打开了:
GatewayIPAddressInformationCollection gwc =
System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].GetIPProperties().GatewayAddresses;
那当然,返回集合GatewayIPAddressInformation
。 因此,如果计算机有多个网关,我怎么能确定这是默认网关?
在实践中,我只看过这个系列包含一个条目,但因为它是作为一个集合实现的,按理说,有些计算机包含多个网关,其中没有一个被标记为“默认”。 那么,有没有一种方法来确定的默认还是这一切只是凭空猜测?
Answer 1:
这应该是第一个启用的网络接口的第一个有效并启用网关地址:
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
返回地址。
这就是说,建议的方式来做到这一点使用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;
}
Answer 2:
通过返回的第一个IP地址traceroute
命令会。你也可以使用这个事实,为获得gateway.You可以找到一个很好的实现网关tracerout
这里: 路由跟踪和Ping在C#
Answer 3:
我知道这是一个稍微大一点的问题,而是,我刚刚临到需要检索本地网关的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;
}
Answer 4:
一直在寻找一个怪异把戏来确定本地IP地址? 然而,做到这一点非常稳健与先前的方法呢?
[见端对响应于@caesay]
这可能是你在找什么。
using (var s = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram,ProtocolType.Udp))
{
s.Bind( new System.Net.IPEndPoint(System.Net.IPAddress.Any,0));
s.Connect("google.com",0);
var ipaddr = s.LocalEndPoint as System.Net.IPEndPoint;
var addr = ipaddr.Address.ToString();
Console.WriteLine(addr);
}
这将创建一个UDP套接字,但不会在其发送的数据。 然后,您可以看到本地接口和地址的套接字是必然。 您必须提供在这里我用google.com的IP地址或主机名,将由操作系统来确定哪个接口插座将被绑定到了,你会发现使用这种方法是什么IP地址。 对于IP地址,或者你使用主机名的99%+,你会得到界面+地址在缺省路由用于交通。
虽然这是一个有点钝,我怀疑这是比上面,人们使用的PInvoke呼叫,通过扫描结构,看看他们是否能找到接口中的方法更可靠。
当然,我发现它更强大的对我的3个双界面系统不是通过NetworkInterface.GetAllNetworkInterfaces()使用启发式方法来揣摩默认接口地址的扫描结果。
[更新/响应@caesay 2019年2月6日] @caesay曾在这里作出了一个极好点,所以我已经从使用UdpClient到套接字切换样品,并且明确地称为Socket.Connect()绑定()之后。 我还审查了connect()和LocalEndPoint框架的源代码,都立即致电其相应的Win32操作系统的系统调用,而不会减慢或懒惰有关调用到操作系统。 在Win32绑定页面上显示“应用程序可以调用bind学习地址和已分配到插座端口后使用getsockname。如果Internet地址等于INADDR_ANY或IN6ADDR_ANY,直到套接字getsockname不一定能提供地址连接的”。 这种情况现在已经明确处理,并审议了框架的源代码,IP地址应始终可用的connect()调用之后。
Answer 5:
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());
Answer 6:
根据对@ caesay的答案,这是一个更好的答案@ midspace的评论:
public static IPAddress GetDefaultGateway()
{
var gateway_address = NetworkInterface.GetAllNetworkInterfaces()
.Where(e => e.OperationalStatus == OperationalStatus.Up)
.SelectMany(e => e.GetIPProperties().GatewayAddresses)
.FirstOrDefault();
if (gateway_address == null) return null;
return gateway_address.Address;
}
我警告说,它不是一个完整的解决方案,如果傻冒找负责互联网接入的主界面,您应该结合喜欢使用Win32 API的其他方法GetBestInterface找到连接到目的地址的最佳接口。
你可以在这里找到用法示例: http://www.pinvoke.net/default.aspx/iphlpapi.getbestinterface
Answer 7:
我刚刚碰到这个,将使用下面的代码 - 基本上它看起来没有回送,并已启动且有网关和单播地址的接口。 从接口I然后得到一个非暂时性的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;
}
}
Answer 8:
我认为你应该遍历这个收集和显示所有的网关,因为如果有很多网关适配器,他们都被认为是默认到该适配器
文章来源: Get the Default Gateway