获取本地IP地址

384

互联网上有很多地方向你展示如何获取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感兴趣:例如,如果某人想要访问我计算机上的共享文件夹,那么我会给他这个IP。

如果我没有连接到网络,并且直接通过调制解调器连接到互联网,则我希望得到一个错误。如何使用C#查看计算机是否连接到网络,如果连接,则获取局域网IP地址。


2
如果我没有连接到网络但连接到互联网,这个语句似乎有矛盾。你是想确定计算机连接到私人局域网还是互联网吗? - Andy
6
警告:一台计算机可以拥有多个IP接口,例如局域网和WiFi。如果您将服务绑定到特定的硬件设备(比如局域网),您需要该局域网的IP地址。以下大部分示例将返回找到的“第一个”或“最后一个”IP地址。如果您拥有超过2个IP地址,您的程序可能50%的时间正常工作,这取决于操作系统返回IP地址的随机顺序。 - Mark Lakata
@MarkLakata 我也考虑到了同样的问题。我在下面的答案中提供的函数可以处理它。你可以指定你想要从哪种类型的网络接口获取IP地址。 - compman2408
3
只是提一下,如果你在谷歌上搜索Unity3D,它们的API中有Network.player.ipAddress。 - Fattie
@MarkLakata 严格来说,“第一个”或“最后一个”IP 就是“正确”的IP,因为浏览器可能使用任何可用的IP。可能一个好的修正应该是返回与机器相关联的每个IP。 - UncaAlby
28个回答

7

@mrchief,我今天发现了这个答案,虽然它返回了一个错误的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;
}

2
你是指Logmein Hamachi吗?它是一种VPN解决方案,可以调整网络堆栈。另外,作为VPN,当连接时返回VPN分配的IP似乎是合理的(这只是我的猜测)。 - Mrchief
2
完全不可靠。192.0.0.0/8 不仅不是正确的私有 IP 地址测试(有 3 个范围,都与此不同),而且它可能是公司网络范围,因此并不是那么“本地”。 - ivan_pozdeev

5

这是我使用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;
}

4

我之前也曾经苦恼于获取正确的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);

3

使用以下这些:

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与网关IP地址处于同一子网中,这将破坏我们基于漂亮的LINQ方法的能力,也需要更多的代码)


1
此解决方案获取配置在接口上的真实IP。大多数基于DNS的解决方案只是询问其他人(DNS)它认为本地IP可能是什么。 - Holger Böhnke

3

前提条件:您需要添加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));

2
使用Linq更新Mrchief的答案,我们将会有以下代码:
public static IPAddress GetLocalIPAddress()
{
   var host = Dns.GetHostEntry(Dns.GetHostName());
   var ipAddress= host.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
   return ipAddress;
}

2
这将返回具有网关地址和单播地址的任何接口的地址,分别在两个列表中,即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());
}

1

过时的已经消失,这对我来说可行。

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

1
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 总是为空。 - aj.toulan

1
请记住,在一般情况下,您可能会有多个NAT转换,并且多个DNS服务器,每个服务器都在不同的NAT转换级别上运行。
如果您使用运营商级NAT,并希望与相同运营商的其他客户进行通信,那该怎么办?在一般情况下,您永远不知道,因为您可能会在每个NAT转换中都使用不同的主机名。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接