【问题标题】:Query Local IP Address查询本地IP地址
【发布时间】:2016-06-21 09:23:07
【问题描述】:

我需要通过 Windows 8 WinRT/Metro 应用了解我的实际本地 IP 地址(即不是环回地址)。我需要这个有几个原因。最简单的是,在应用程序的 UI 中,我想显示一些文本,例如“您的本地网络 IP 地址是:[从代码查询的 IP]”。

我们还将地址用于一些额外的网络通信。这些通讯是完全有效的,因为如果我查看控制面板中的 IP 地址,然后将其硬编码到应用程序中,它们都可以正常工作。在对话框中要求用户查看地址并手动输入它是我非常非常想避免的事情。

我认为以编程方式获取地址不会是一项复杂的任务,但我的搜索引擎和 StackOverflow 技能都空了。

此时,我开始考虑进行 UDP 广播/侦听循环,以听取我自己的请求并从中提取地址,但这看起来确实是一个 hackey kludge。在新的 WinRT 东西中是否有 API 可以让我到达那里?

请注意,我说的是“WinRT 应用程序。这意味着像 Dns.GetHostEntryNetworkInterface.GetAllInterfaces() 这样的典型机制不起作用。

【问题讨论】:

  • Windows 只知道接口,如果有人将本地网络 IP 地址分配给网络设备,那就是地址(它完全有效)。你到底想用IP地址做什么?除了接口知道的 IP 地址之外,您不太可能对任何内容进行 UDP 广播/侦听,而该地址通常是在所述网络之外无效的本地网络地址。
  • @Ramhound:不确定我应该看什么——而且这个文档与我在 Consumer Preview 和 VS11 Beta 中看到的行为不符。例如,文档显示 NetworkIntrface.GetAllNetworkInterfaces() 应该可以工作,但它不存在。

标签: c# windows-runtime


【解决方案1】:

经过大量挖掘,我使用NetworkInformationHostName 找到了您需要的信息。

NetworkInformation.GetInternetConnectionProfile 检索与本地计算机当前使用的互联网连接关联的连接配置文件。

NetworkInformation.GetHostNames 检索主机名列表。这并不明显,但这包括作为字符串的 IPv4 和 IPv6 地址。

使用这些信息,我们可以获得连接到互联网的网络适配器的 IP 地址,如下所示:

public string CurrentIPAddress()
{
    var icp = NetworkInformation.GetInternetConnectionProfile();

    if (icp != null && icp.NetworkAdapter != null)
    {
        var hostname =
            NetworkInformation.GetHostNames()
                .SingleOrDefault(
                    hn =>
                    hn.IPInformation != null && hn.IPInformation.NetworkAdapter != null
                    && hn.IPInformation.NetworkAdapter.NetworkAdapterId
                    == icp.NetworkAdapter.NetworkAdapterId);

        if (hostname != null)
        {
            // the ip address
            return hostname.CanonicalName;
        }
    }

    return string.Empty;
}

请注意,HostName 具有属性 CanonicalName、DisplayName 和 RawName,但它们似乎都返回相同的字符串。

我们也可以通过类似下面的代码获取多个适配器的地址:

private IEnumerable<string> GetCurrentIpAddresses()
{
    var profiles = NetworkInformation.GetConnectionProfiles().ToList();

    // the Internet connection profile doesn't seem to be in the above list
    profiles.Add(NetworkInformation.GetInternetConnectionProfile());

    IEnumerable<HostName> hostnames =
        NetworkInformation.GetHostNames().Where(h => 
            h.IPInformation != null &&
            h.IPInformation.NetworkAdapter != null).ToList();

    return (from h in hostnames
            from p in profiles
            where h.IPInformation.NetworkAdapter.NetworkAdapterId ==
                  p.NetworkAdapter.NetworkAdapterId
            select string.Format("{0}, {1}", p.ProfileName, h.CanonicalName)).ToList();
}

【讨论】:

  • 确实是一个挑战。我的团队很快将需要支持 Windows 2003+(包括 Windows 8)。痛苦在于像查找当前机器的 IP 地址这样简单的事情需要任何“挖掘”。
  • 支持 iOS 需要阅读文档。我希望更多的开发人员开始定期阅读文档。
  • hn.NetworkAdapterWindows.Networking.Connectivity.NetworkInformation 类的最终版本中已被替换为hn.IPInformation.NetworkAdaptervar hostname 行的修订版本应类似于 var hostname = NetworkInformation.GetHostNames().SingleOrDefault(hn =&gt; hn.IPInformation != null &amp;&amp; hn.IPInformation.NetworkAdapter != null &amp;&amp; hn.IPInformation.NetworkAdapter.NetworkAdapterId == icp.NetworkAdapter.NetworkAdapterId);
  • @AndrewB:我刚刚尝试了上述两种方法,它们对我有用。 10.0.0.1 是标准的私有 IP 地址,例如 192.168.x.x。我觉得还可以。
  • 我建议在查询中添加 && hn.Type == HostNameType.Ipv4。因为如果你也有 IpV6,我会收到一个错误,就像我一样,并且会因为 SingleOrDefault 而引发异常。
【解决方案2】:

关于接受的答案,你只需要这个:

HostName localHostName = NetworkInformation.GetHostNames().FirstOrDefault(h =>
                    h.IPInformation != null &&
                    h.IPInformation.NetworkAdapter != null);

您可以通过这种方式获取本地IP地址:

string ipAddress = localHostName.RawName; //XXX.XXX.XXX.XXX

使用的命名空间:

using System.Linq;
using Windows.Networking;
using Windows.Networking.Connectivity;

【讨论】:

  • 这个答案完全不正确。它可能在特定的网络配置中工作,但尝试将虚拟机添加到系统和虚拟交换机中,并且第一个返回的主机名可能是完全不可用的虚拟交换机 IP。
猜你喜欢
  • 1970-01-01
  • 2022-12-15
  • 1970-01-01
  • 2018-03-17
  • 2011-07-02
  • 2011-10-11
  • 2012-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多