【问题标题】:Get local IP address获取本地IP地址
【发布时间】:2011-10-11 19:08:00
【问题描述】:

在互联网上有几个地方向您展示了如何获取 IP 地址。其中很多看起来像这个例子:

String strHostName = string.Empty;
// Getting Ip address of local machine...
// First get the host name of local machine.
strHostName = Dns.GetHostName();
Console.WriteLine("Local Machine's Host Name: " + strHostName);
// Then using host name, get the IP address list..
IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
IPAddress[] addr = ipEntry.AddressList;

for (int i = 0; i < addr.Length; i++)
{
    Console.WriteLine("IP Address {0}: {1} ", i, addr[i].ToString());
}
Console.ReadLine();

在这个例子中,我得到了几个 IP 地址,但我只对路由器分配给运行程序的计算机感兴趣:如果某人希望访问共享文件夹,我会给他的 IP 地址例如我的电脑。

如果我没有连接到网络,而是通过没有路由器的调制解调器直接连接到互联网,那么我想得到一个错误。如何查看我的计算机是否使用 C# 连接到网络,如果是,则获取 LAN IP 地址。

【问题讨论】:

  • If I am not connected to a network and I am connected to the internet 这个说法似乎自相矛盾。您是否想弄清楚您的计算机是连接到专用 LAN 还是 Internet?
  • 作为警告:一台计算机可以有多个 IP 接口,例如 LAN 和 WiFi。如果您将服务绑定到特定的硬件(例如 LAN),则需要 LAN 的 IP。以下大多数示例将返回找到的“第一个”或“最后一个”IP 地址。如果您有超过 2 个 IP 地址,您的程序可能会在 50% 的时间内运行,具体取决于操作系统返回 IP 地址的随机顺序。
  • @MarkLakata 我想到了同样的问题。我下面的答案中的功能将处理它。您可以指定您希望获得 IP 地址的网络接口类型。
  • 只是 FTR,如果你在这里用谷歌搜索 Unity3D,它的 API 中是 Network.player.ipAddress
  • @MarkLakata 严格来说,“第一个”或“最后一个”IP“正确的”IP,因为浏览器可以使用任何可用的 IP。一个好的修正应该是返回与机器相关的每个 IP。

标签: c# networking


【解决方案1】:

获取本地IP地址:

public static string GetLocalIPAddress()
{
    var host = Dns.GetHostEntry(Dns.GetHostName());
    foreach (var ip in host.AddressList)
    {
        if (ip.AddressFamily == AddressFamily.InterNetwork)
        {
            return ip.ToString();
        }
    }
    throw new Exception("No network adapters with an IPv4 address in the system!");
}

检查您是否已连接:

System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();

【讨论】:

  • 如果你使用 vm virtual box、genymotion 等东西,将无法工作。
  • 同意 PaulEffect。这种方法不仅对多网卡不利,而且不区分 IPv6 和 IPv4 地址。
  • @John AddressFamily.InterNetwork 是 IP v4 而 AddressFamily.InterNetworkV6 是 IP v6
  • 我正在使用 Geraldo H 答案,但是如果有人在使用它,您可能需要删除所有以 1 结尾的 ip,因此它将删除环回和 virtualbox/vmware 默认 ip
  • 您似乎在使用 VMWare 或其他虚拟化软件。 OP没有要求这样做,所以我认为因此而拒绝投票有点苛刻。如果您有 VMWare 或多个 NIC,其他一些答案已经提供了线索。
【解决方案2】:

当本地机器上有多个可用的 IP 地址时,有一种更准确的方法。 Connect UDP 套接字并读取其本地端点:

string localIP;
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
    socket.Connect("8.8.8.8", 65530);
    IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
    localIP = endPoint.Address.ToString();
}

Connect 在 UDP 套接字上具有以下效果:它为 Send/Recv 设置目标,丢弃来自其他地址的所有数据包,并且 - 这就是我们使用的 - 将套接字转换为“已连接”状态,设置其适当的字段。这包括根据系统的路由表检查到目的地的路由是否存在,并相应地设置本地端点。最后一部分似乎没有正式记录,但它看起来像是Berkeley sockets API 的一个不可或缺的特征(UDP“连接”状态的副作用),它在 Windows and Linux 的版本和发行版中都能可靠地工作。

因此,此方法将提供用于连接到指定远程主机的本地地址。没有建立真正的连接,因此指定的远程 ip 可能无法访问。

【讨论】:

  • 这是满足我需求的最佳解决方案。在我的情况下,我有很多网卡和一些无线连接。我需要根据激活的连接获取首选 IP 地址。
  • 没有网络连接——无论如何,你没有IP地址。因此,代码仍然有效,尽管添加 try..catch 以处理这种情况是谨慎的,如果抛出 SocketException 则返回类似“127.0.0.1”的内容。
  • @PatrickSteele,是的,它返回特定目标的首选出站 IP 地址。如果你想获取你的 LAN ip 地址,请尝试将目标指示为你 LAN 中的某个 ip
  • 此方法适用于具有 dotnet 核心的 mac,而目前接受的答案不适用。
  • 此解决方案的运行速度比接受的答案(由 Mrchief 提供)快约 4 倍。这应该是真正的答案
【解决方案3】:

我知道这可能是在踢死马,但也许这可以帮助某人。我到处寻找找到我的本地 IP 地址的方法,但我发现它到处都说要使用:

Dns.GetHostEntry(Dns.GetHostName());

我一点也不喜欢这样,因为它只会获取分配给您计算机的所有地址。如果您有多个网络接口(现在几乎所有计算机都这样做),您不知道哪个地址与哪个网络接口对应。经过大量研究后,我创建了一个函数来使用 NetworkInterface 类并从中提取信息。这样我就可以知道它是什么类型的接口(以太网、无线、环回、隧道等),它是否处于活动状态,等等。

public string GetLocalIPv4(NetworkInterfaceType _type)
{
    string output = "";
    foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
        {
            foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
            {
                if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                {
                    output = ip.Address.ToString();
                }
            }
        }
    }
    return output;
}

现在获取以太网网络接口调用的 IPv4 地址:

GetLocalIPv4(NetworkInterfaceType.Ethernet);

或者您的无线接口:

GetLocalIPv4(NetworkInterfaceType.Wireless80211);

如果您尝试获取无线接口的 IPv4 地址,但您的计算机没有安装无线网卡,它只会返回一个空字符串。以太网接口也是如此。

希望这对某人有所帮助! :-)

编辑:

有人指出(感谢@NasBanov),尽管此函数以比使用Dns.GetHostEntry(Dns.GetHostName()) 更好的方式提取IP 地址,但它在支持多个相同类型或多个接口方面表现不佳单个接口上的 IP 地址。当可能分配了多个地址时,它只会返回一个 IP 地址。要返回所有这些分配的地址,您可以简单地操纵原始函数以始终返回一个数组而不是单个字符串。例如:

public static string[] GetAllLocalIPv4(NetworkInterfaceType _type)
{
    List<string> ipAddrList = new List<string>();
    foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
        {
            foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
            {
                if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                {
                    ipAddrList.Add(ip.Address.ToString());
                }
            }
        }
    }
    return ipAddrList.ToArray();
}

现在此函数将返回特定接口类型的所有分配地址。现在只获取一个字符串,您可以使用.FirstOrDefault() 扩展来返回数组中的第一项,或者如果它为空,则返回一个空字符串。

GetLocalIPv4(NetworkInterfaceType.Ethernet).FirstOrDefault();

【讨论】:

  • 这是一个更好的解决方案,因为很多地方都没有 DNS 可用性,而且接口可以有多个 IP 地址。我也使用了类似的方法。
  • 这个问题是每个接口只返回 1 个 IP 地址...最后一个 IP,foreach。
  • @compman2408 - 不正确,单个接口可以有多个 IP,请参阅 en.wikipedia.org/wiki/Multihoming#Variants 了解所有组合。明显的例子是同时运行 IPv4 和 IPv6 时,但过去我有一个以太网适配器参与多个 IPv4 网络。也许不寻常 - 但完全合法。例如。对于 Windows,请参阅 windowsnetworking.com/articles-tutorials/windows-2003/…
  • @NasBanov 这个函数只是为了获取 IPv4 地址而设置的,所以我什至不打算谈论 IPv6 及其当前的无用性。我知道多宿主连接到多个接口上的多个网络但是从未听说过在同一个接口上连接到多个网络。即使您似乎是正确的,实际上是有可能的,
  • 谢谢你。仅供参考,至少在 OSX 上的 .NET 3.5 mono 上 item.OperationalStatus 总是返回 Unknown
【解决方案4】:

重构 Mrcheif 的代码以利用 Linq(即 .Net 3.0+)。 .

private IPAddress LocalIPAddress()
{
    if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
    {
        return null;
    }

    IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());

    return host
        .AddressList
        .FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
}

:)

【讨论】:

  • 我有几个 IP 地址作为“Inter Network”,这个解决方案确实有效,并返回了正确的地址。 Mrchief 的另一张只给了我最后一张。所以实际上这个应该是正确的;)
  • @KeenoraFluffball - 这个给你第一个,而这个给你最后一个(反之亦然,取决于列表的构造方式)。无论哪种方式,都不正确 - 如果给您的 IP 地址超过 1 个,您需要知道您使用的是哪个网络。通过取第一个或最后一个来猜测不是正确的解决方案。
  • 可能还想包括 AddressFamily.InterNetworkV6
  • 如果您还必须处理独立 PC,则如果网络不可用则返回 null 是没有用的。我将其替换为“return IPAddress.Loopback;”对应特殊 IP 号 127.0.0.1。
【解决方案5】:

这是一个对我有用的修改版本(来自 compman2408 的版本):

    internal static string GetLocalIPv4(NetworkInterfaceType _type)
    {  // Checks your IP adress from the local network connected to a gateway. This to avoid issues with double network cards
        string output = "";  // default output
        foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) // Iterate over each network interface
        {  // Find the network interface which has been provided in the arguments, break the loop if found
            if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
            {   // Fetch the properties of this adapter
                IPInterfaceProperties adapterProperties = item.GetIPProperties();
                // Check if the gateway adress exist, if not its most likley a virtual network or smth
                if (adapterProperties.GatewayAddresses.FirstOrDefault() != null)
                {   // Iterate over each available unicast adresses
                    foreach (UnicastIPAddressInformation ip in adapterProperties.UnicastAddresses)
                    {   // If the IP is a local IPv4 adress
                        if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {   // we got a match!
                            output = ip.Address.ToString();
                            break;  // break the loop!!
                        }
                    }
                }
            }
            // Check if we got a result if so break this method
            if (output != "") { break; }
        }
        // Return results
        return output;
    }

你可以像这样调用这个方法:

GetLocalIPv4(NetworkInterfaceType.Ethernet);

更改:我正在从分配有网关 IP 的适配器检索 IP。 第二个变化:我添加了 docstrings 和 break 语句以使这种方法更有效。

【讨论】:

  • 聪明的解决方案。我现在正在使用它。
  • 与它的派生代码有相同的问题:它只返回一个 IP,一个来自许多的随机 IP - 它不一定是您需要的。它赢得了ademiller.com/blogs/tech/2008/06/it-works-on-my-machine-award
  • @NasBanov,我确实赚到了,正如我在帖子中所说:“这对我有用”。 :-)
  • 这是要走的路,谢谢你。当您安装了模拟器的环回开关后,所有其他变体都会失败,而这个变体会成功!
  • 为什么你只返回你找到的最后一个IP地址,而不是第一个?最内部的ifreturn 中的简单break 可以解决问题。
【解决方案6】:

这是我找到的获取当前 IP 的最佳代码,避免获取 VMWare 主机或其他无效 IP 地址。

public string GetLocalIpAddress()
{
    UnicastIPAddressInformation mostSuitableIp = null;

    var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

    foreach (var network in networkInterfaces)
    {
        if (network.OperationalStatus != OperationalStatus.Up)
            continue;

        var properties = network.GetIPProperties();

        if (properties.GatewayAddresses.Count == 0)
            continue;

        foreach (var address in properties.UnicastAddresses)
        {
            if (address.Address.AddressFamily != AddressFamily.InterNetwork)
                continue;

            if (IPAddress.IsLoopback(address.Address))
                continue;

            if (!address.IsDnsEligible)
            {
                if (mostSuitableIp == null)
                    mostSuitableIp = address;
                continue;
            }

            // The best IP is the IP got from DHCP server
            if (address.PrefixOrigin != PrefixOrigin.Dhcp)
            {
                if (mostSuitableIp == null || !mostSuitableIp.IsDnsEligible)
                    mostSuitableIp = address;
                continue;
            }

            return address.Address.ToString();
        }
    }

    return mostSuitableIp != null 
        ? mostSuitableIp.Address.ToString()
        : "";
}

【讨论】:

  • 您可能应该解释一下,为什么这段代码是答案的解决方案。如果您已连接到互联网并且这是否会导致错误,您真的可以得到关于该问题的答案吗?
  • 其他方式不使用 IsDnsEligible 和 PrefixOrigin 验证。
  • @PhilippM 如果地址不符合 DNS 条件,则它是保留的内部 IP。它不是互联网提供商主机。如果 PrefixOrigin 是由 DHCP 服务器提供的,那么这可能是最好的地址选择。这是对我有用的独特功能!
  • @user1551843 - 太好了,谢谢。我使用的是旧的已折旧的 GetHostByName 方法,但它返回的是 VMWare 适配器的 IP :)
  • 这是在 vpn + 无线上对我有用的唯一解决方案。谢谢。
【解决方案7】:

我认为使用 LINQ 更容易:

Dns.GetHostEntry(Dns.GetHostName())
   .AddressList
   .First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
   .ToString()

【讨论】:

  • 那不是 LINQ,那是扩展方法和 lambda。有区别。
  • @Mark - 如果您不添加“使用 System.Linq;”但是你不能使用“First”扩展方法
  • 这是因为扩展方法在 System.Linq 命名空间中的 Enumerable 类中。它仍然不是 LINQ。
  • 马克,即使是这种简短的形式,该语句确实使用了带有方法(lambda)语法的 LINQ-to-objects。查询语法只是被编译成 IEnumerable 扩展方法调用链的语法糖,这就是 LINQ-to-objects。资料来源:撰写了一个 LINQ-to-SQL 提供程序和一系列关于该主题的文章。
【解决方案8】:

使用 linq 表达式获取 IP 的其他方式:

public static List<string> GetAllLocalIPv4(NetworkInterfaceType type)
{
    return NetworkInterface.GetAllNetworkInterfaces()
                   .Where(x => x.NetworkInterfaceType == type && x.OperationalStatus == OperationalStatus.Up)
                   .SelectMany(x => x.GetIPProperties().UnicastAddresses)
                   .Where(x => x.Address.AddressFamily == AddressFamily.InterNetwork)
                   .Select(x => x.Address.ToString())
                   .ToList();
}

【讨论】:

    【解决方案9】:

    为了一笑,我想我会尝试使用新的 C# 6 空条件运算符来获取单个 LINQ 语句。看起来很疯狂,而且可能效率极低,但它确实有效。

    private string GetLocalIPv4(NetworkInterfaceType type = NetworkInterfaceType.Ethernet)
    {
        // Bastardized from: http://stackoverflow.com/a/28621250/2685650.
    
        return NetworkInterface
            .GetAllNetworkInterfaces()
            .FirstOrDefault(ni =>
                ni.NetworkInterfaceType == type
                && ni.OperationalStatus == OperationalStatus.Up
                && ni.GetIPProperties().GatewayAddresses.FirstOrDefault() != null
                && ni.GetIPProperties().UnicastAddresses.FirstOrDefault(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork) != null
            )
            ?.GetIPProperties()
            .UnicastAddresses
            .FirstOrDefault(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork)
            ?.Address
            ?.ToString()
            ?? string.Empty;
    }
    

    逻辑由Gerardo H 提供(并通过引用compman2408)。

    【讨论】:

    • 绝对有趣(+1),但实际上根本不需要低效。让我想起了用 LISP 或 Forth 编程:-)
    • 所以..不是我要写的。这种奇怪的“?”。当使用 Select/SelectMany(SelectMany 可以增加或减少长度)进行转换时,可以重写(或“固定”)链接的 LINQ-to-Objects,以便最终形式为 IEnumeable 以便“FirstOrDefault() ? ? string.Empty" 就足够了。
    • 我不确定您是否可以说空条件运算符是“奇怪的”,但我确定我认为这段代码(正如我所说的)“非常疯狂”。
    • 一旦你使用了第一个空条件,他们应该都拥有它。如果没有匹配的网络接口,它将在.UnicastAddresses 上抛出空指针异常
    【解决方案10】:

    @mrcheif 我今天找到了这个答案,它非常有用,虽然它确实返回了错误的 IP(不是因为代码不工作),但是当你运行 Himachi 之类的东西时,它给出了错误的互联网 IP。

    public static string localIPAddress()
    {
        IPHostEntry host;
        string localIP = "";
        host = Dns.GetHostEntry(Dns.GetHostName());
    
        foreach (IPAddress ip in host.AddressList)
        {
            localIP = ip.ToString();
    
            string[] temp = localIP.Split('.');
    
            if (ip.AddressFamily == AddressFamily.InterNetwork && temp[0] == "192")
            {
                break;
            }
            else
            {
                localIP = null;
            }
        }
    
        return localIP;
    }
    

    【讨论】:

    • 你是说 Logmein Hamachi 吗?这是一个 VPN 解决方案,它修补了网络堆栈。此外,作为 VPN,它在连接时返回 VPN 分配的 IP 似乎是合理的(只是我的猜测)。
    • 完全不可靠。 192.0.0.0/8 不仅不是对私有 IP 地址的正确测试(有 3 个范围,都与这个不同),它很可能是一个公司网络范围,所以不是那么“本地”。
    【解决方案11】:

    用一个或多个 LAN 卡和虚拟机测试

    public static string DisplayIPAddresses()
        {
            string returnAddress = String.Empty;
    
            // Get a list of all network interfaces (usually one per network card, dialup, and VPN connection)
            NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
    
            foreach (NetworkInterface network in networkInterfaces)
            {
                // Read the IP configuration for each network
                IPInterfaceProperties properties = network.GetIPProperties();
    
                if (network.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
                       network.OperationalStatus == OperationalStatus.Up &&
                       !network.Description.ToLower().Contains("virtual") &&
                       !network.Description.ToLower().Contains("pseudo"))
                {
                    // Each network interface may have multiple IP addresses
                    foreach (IPAddressInformation address in properties.UnicastAddresses)
                    {
                        // We're only interested in IPv4 addresses for now
                        if (address.Address.AddressFamily != AddressFamily.InterNetwork)
                            continue;
    
                        // Ignore loopback addresses (e.g., 127.0.0.1)
                        if (IPAddress.IsLoopback(address.Address))
                            continue;
    
                        returnAddress = address.Address.ToString();
                        Console.WriteLine(address.Address.ToString() + " (" + network.Name + " - " + network.Description + ")");
                    }
                }
            }
    
           return returnAddress;
        }
    

    【讨论】:

    • 请记住,这个仅适用于以太网。移除 NetworkInterfaceType 限制以支持 wi-fi。
    【解决方案12】:

    只是我使用 LINQ 的更新版本:

    /// <summary>
    /// Gets the local Ipv4.
    /// </summary>
    /// <returns>The local Ipv4.</returns>
    /// <param name="networkInterfaceType">Network interface type.</param>
    IPAddress GetLocalIPv4(NetworkInterfaceType networkInterfaceType)
    {
        var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces().Where(i => i.NetworkInterfaceType == networkInterfaceType && i.OperationalStatus == OperationalStatus.Up);
    
        foreach (var networkInterface in networkInterfaces)
        {
            var adapterProperties = networkInterface.GetIPProperties();
    
            if (adapterProperties.GatewayAddresses.FirstOrDefault() == null)
                    continue;
            foreach (var ip in networkInterface.GetIPProperties().UnicastAddresses)
            {
                if (ip.Address.AddressFamily != AddressFamily.InterNetwork)
                        continue;
    
                return ip.Address;
            }
        }
    
        return null;
    }
    

    【讨论】:

      【解决方案13】:

      先决条件:您必须添加 System.Data.Linq 引用并引用它

      using System.Linq;
      string ipAddress ="";
      IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
      ipAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork));
      

      【讨论】:

        【解决方案14】:

        我也在努力获取正确的 IP。

        我在这里尝试了各种解决方案,但没有一个能提供我想要的效果。几乎所有提供的条件测试都导致没有使用地址。

        这对我有用,希望对您有所帮助...

        var firstAddress = (from address in NetworkInterface.GetAllNetworkInterfaces().Select(x => x.GetIPProperties()).SelectMany(x => x.UnicastAddresses).Select(x => x.Address)
                            where !IPAddress.IsLoopback(address) && address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
                            select address).FirstOrDefault();
        
        Console.WriteLine(firstAddress);
        

        【讨论】:

          【解决方案15】:

          这会从任何接口返回地址,这些接口在 IPV4 和 IPV6 这两个单独的列表中具有网关地址和单播地址。

          public static (List<IPAddress> V4, List<IPAddress> V6) GetLocal()
          {
              List<IPAddress> foundV4 = new List<IPAddress>();
              List<IPAddress> foundV6 = new List<IPAddress>();
          
              NetworkInterface.GetAllNetworkInterfaces().ToList().ForEach(ni =>
              {
                  if (ni.GetIPProperties().GatewayAddresses.FirstOrDefault() != null)
                  {
                      ni.GetIPProperties().UnicastAddresses.ToList().ForEach(ua =>
                      {
                          if (ua.Address.AddressFamily == AddressFamily.InterNetwork) foundV4.Add(ua.Address);
                          if (ua.Address.AddressFamily == AddressFamily.InterNetworkV6) foundV6.Add(ua.Address);
                      });
                  }
              });
          
              return (foundV4.Distinct().ToList(), foundV6.Distinct().ToList());
          }
          

          【讨论】:

          • 整洁的解决方案:)
          【解决方案16】:

          使用这些:

          using System.Net;
          using System.Net.Sockets;
          using System.Net.NetworkInformation;
          using System.Linq;
          

          您可以使用一系列 LINQ 方法来获取最喜欢的 IP 地址。

          public static bool IsIPv4(IPAddress ipa) => ipa.AddressFamily == AddressFamily.InterNetwork;
          
          public static IPAddress GetMainIPv4() => NetworkInterface.GetAllNetworkInterfaces()
          .Select((ni)=>ni.GetIPProperties())
          .Where((ip)=> ip.GatewayAddresses.Where((ga) => IsIPv4(ga.Address)).Count() > 0)
          .FirstOrDefault()?.UnicastAddresses?
          .Where((ua) => IsIPv4(ua.Address))?.FirstOrDefault()?.Address;
          

          这只是查找具有 IPv4 默认网关的第一个网络接口,并获取该接口上的第一个 IPv4 地址。 网络堆栈设计为只有一个默认网关,因此具有默认网关的堆栈是最好的。

          警告:如果您的主适配器有多个 IPv4 地址的设置异常,则此仅获取 第一个一个。 (在这种情况下获取最佳方案的解决方案包括获取网关 IP,并检查哪个单播 IP 与网关 IP 地址在同一子网中,这将扼杀我们创建基于 LINQ 方法的解决方案的能力,如以及更多的代码)

          【讨论】:

          • 此方案获取接口上配置的真实IP。大多数基于 DNS 的解决方案只是询问其他人(DNS)它认为本地 IP 可能是什么。
          【解决方案17】:
          string str="";
          
          System.Net.Dns.GetHostName();
          
          IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(str);
          
          IPAddress[] addr = ipEntry.AddressList;
          
          string IP="Your Ip Address Is :->"+ addr[addr.Length - 1].ToString();
          

          【讨论】:

          • str 始终为空
          【解决方案18】:

          请记住,在一般情况下,您可以进行多个 NAT 转换和多个 dns 服务器,每个服务器都在不同的 NAT 转换级别上运行。

          如果您有运营商级 NAT,并且想与同一运营商的其他客户通信怎么办?在一般情况下,您永远无法确定,因为您可能会在每次 NAT 转换时出现不同的主机名。

          【讨论】:

            【解决方案19】:

            已过时,这对我有用

            public static IPAddress GetIPAddress()
            { 
             IPAddress ip = Dns.GetHostAddresses(Dns.GetHostName()).Where(address => 
             address.AddressFamily == AddressFamily.InterNetwork).First();
             return ip;
            }
            

            【讨论】:

              【解决方案20】:

              用 Linq 更新 Mrchief 的答案,我们将:

              public static IPAddress GetLocalIPAddress()
              {
                 var host = Dns.GetHostEntry(Dns.GetHostName());
                 var ipAddress= host.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
                 return ipAddress;
              }
              

              【讨论】:

                【解决方案21】:
                Imports System.Net
                Imports System.Net.Sockets
                Function LocalIP()
                    Dim strHostName = Dns.GetHostName
                    Dim Host = Dns.GetHostEntry(strHostName)
                    For Each ip In Host.AddressList
                        If ip.AddressFamily = AddressFamily.InterNetwork Then
                            txtIP.Text = ip.ToString
                        End If
                    Next
                
                    Return True
                End Function
                

                在相同的操作下

                Function LocalIP()
                
                   Dim Host As String =Dns.GetHostEntry(Dns.GetHostName).AddressList(1).MapToIPv4.ToString
                
                   txtIP.Text = Host
                
                   Return True
                
                End Function
                

                【讨论】:

                • 下面的例子是相同的操作 Function LocalIP() Dim Host As String = Dns.GetHostEntry(Dns.GetHostName).AddressList(1).MapToIPv4.ToString txtIP.Text = Host Return True End Function跨度>
                【解决方案22】:

                另外只是获取客户端IP的简单代码:

                        public static string getclientIP()
                        {
                            var HostIP = HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : "";
                            return HostIP;
                        }
                

                希望对你有帮助。

                【讨论】:

                • 如果您有 HttpContext 手头,这是相关的,但在某些情况下我们不会,所以应该有一个替代解决方案。
                【解决方案23】:

                修改了 compman2408 的代码,使其能够遍历每个 NetworkInterfaceType

                public static string GetLocalIPv4 (NetworkInterfaceType _type) {
                    string output = null;
                    foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces ()) {
                        if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up) {
                            foreach (UnicastIPAddressInformation ip in item.GetIPProperties ().UnicastAddresses) {
                                if (ip.Address.AddressFamily == AddressFamily.InterNetwork) {
                                    output = ip.Address.ToString ();
                                }
                            }
                        }
                    }
                    return output;
                }
                

                你可以这样称呼它:

                static void Main (string[] args) {
                    // Get all possible enum values:
                    var nitVals = Enum.GetValues (typeof (NetworkInterfaceType)).Cast<NetworkInterfaceType> ();
                
                    foreach (var nitVal in nitVals) {
                        Console.WriteLine ($"{nitVal} => {GetLocalIPv4 (nitVal) ?? "NULL"}");
                    }
                }
                

                【讨论】:

                  【解决方案24】:

                  已经有很多答案了,但我仍在贡献我的一个:

                  public static IPAddress LocalIpAddress() {
                      Func<IPAddress, bool> localIpPredicate = ip =>
                          ip.AddressFamily == AddressFamily.InterNetwork &&
                          ip.ToString().StartsWith("192.168"); //check only for 16-bit block
                      return Dns.GetHostEntry(Dns.GetHostName()).AddressList.LastOrDefault(localIpPredicate);
                  }
                  

                  一个班轮:

                  public static IPAddress LocalIpAddress() => Dns.GetHostEntry(Dns.GetHostName()).AddressList.LastOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork && ip.ToString().StartsWith("192.168"));
                  

                  注意:从最后开始搜索,因为在设备中添加了一些接口后它仍然有效,例如 MobileHotspot、VPN 或其他花哨的虚拟适配器。

                  【讨论】:

                  • 那么如果我的本地 IP 是 10.0.2.3 是不是找不到?这段代码真的很奇怪。
                  • @frankhommers 说只检查 16 位块
                  • 16 位块也可以是 192.168 以外的其他东西
                  【解决方案25】:
                  Dns.GetHostEntry(Dns.GetHostName()).AddressList[1].MapToIPv4() //returns 192.168.14.1
                  

                  【讨论】:

                  • 您的答案应该包含关于它如何适用于 OP 案例以及未来读者的描述。
                  • 最好为未来的读者提供对答案的解释。
                  • 在某些情况下可能会抛出 OutOfRangeException。
                  【解决方案26】:

                  这是最短的方法:

                  Dns.GetHostEntry(
                      Dns.GetHostName()
                  ).AddressList.AsEnumerable().Where(
                      ip=>ip.AddressFamily.Equals(AddressFamily.InterNetwork)
                  ).FirstOrDefault().ToString()
                  

                  【讨论】:

                  • edit您的帖子包含解释
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-11-29
                  • 2011-04-08
                  • 2021-01-28
                  • 2011-02-10
                  • 2019-02-09
                  • 1970-01-01
                  相关资源
                  最近更新 更多