想象一下,我有两台局域网的PC,一台连接到互联网另一台连接到本地网络,如何通过C#检测连接到互联网的IP?
试试这个:
static IPAddress getInternetIPAddress() { try { IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName()); IPAddress gateway = IPAddress.Parse(getInternetGateway()); return findMatch(addresses, gateway); } catch (FormatException e) { return null; } } static string getInternetGateway() { using (Process tracert = new Process()) { ProcessStartInfo startInfo = tracert.StartInfo; startInfo.FileName = "tracert.exe"; startInfo.Arguments = "-h 1 208.77.188.166"; // www.example.com startInfo.UseShellExecute = false; startInfo.RedirectStandardOutput = true; tracert.Start(); using (StreamReader reader = tracert.StandardOutput) { string line = ""; for (int i = 0; i < 9; ++i) line = reader.ReadLine(); line = line.Trim(); return line.Substring(line.LastIndexOf(' ') + 1); } } } static IPAddress findMatch(IPAddress[] addresses, IPAddress gateway) { byte[] gatewayBytes = gateway.GetAddressBytes(); foreach (IPAddress ip in addresses) { byte[] ipBytes = ip.GetAddressBytes(); if (ipBytes[0] == gatewayBytes[0] && ipBytes[1] == gatewayBytes[1] && ipBytes[2] == gatewayBytes[2]) { return ip; } } return null; }
请注意,此实现findMatch()
依赖于C类匹配.如果您想支持B类匹配,只需省略检查即可ipBytes[2] == gatewayBytes[2]
.
编辑历史:
更新使用www.example.com
.
更新为包含getInternetIPAddress()
,以显示如何使用其他方法.
FormatException
如果getInternetGateway()
无法解析网关IP,则更新以捕获.(如果网关路由器配置为不响应traceroute请求,则会发生这种情况.)
引用Brian Rasmussen的评论.
更新为使用www.example.com的IP,以便即使DNS服务器关闭也能正常工作.
Internet连接必须与默认网关位于同一IP网络上.
如果你能够到达"互联网",那么从IP地址无法告诉你真的万无一失.基本上,您可以与自己的IP网络进行通信.其他一切都必须通过网关.因此,如果您看不到网关,则仅限于本地IP网络.
但是,网关依赖于其他网关,因此即使您可以访问网关,也可能无法访问其他网络.这可能是由于例如过滤或缺少到期望网络的路由.
实际上,从这个意义上谈论互联网是没有意义的,因为在任何特定时刻你可能永远无法访问整个互联网.因此,找出您需要能够访问和验证该网络的连接.
我建议这个简单的代码,因为tracert
并不总是有效,并且whatsmyip.com不是专门为此目的而设计的:
private void GetIP() { WebClient wc = new WebClient(); string strIP = wc.DownloadString("http://checkip.dyndns.org"); strIP = (new Regex(@"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")).Match(strIP).Value; wc.Dispose(); return strIP; }
这是我尝试获取默认IPv4地址而不必诉诸DNS或外部进程调用ipconfig和route等命令.希望.Net的下一个版本将提供对Windows路由表的访问.
public static IPAddress GetDefaultIPv4Address() { var adapters = from adapter in NetworkInterface.GetAllNetworkInterfaces() where adapter.OperationalStatus == OperationalStatus.Up && adapter.Supports(NetworkInterfaceComponent.IPv4) && adapter.GetIPProperties().GatewayAddresses.Count > 0 && adapter.GetIPProperties().GatewayAddresses[0].Address.ToString() != "0.0.0.0" select adapter; if (adapters.Count() > 1) { throw new ApplicationException("The default IPv4 address could not be determined as there are two interfaces with gateways."); } else { UnicastIPAddressInformationCollection localIPs = adapters.First().GetIPProperties().UnicastAddresses; foreach (UnicastIPAddressInformation localIP in localIPs) { if (localIP.Address.AddressFamily == AddressFamily.InterNetwork && !localIP.Address.ToString().StartsWith(LINK_LOCAL_BLOCK_PREFIX) && !IPAddress.IsLoopback(localIP.Address)) { return localIP.Address; } } } return null; }