当前位置:  开发笔记 > 编程语言 > 正文

获取本地IP地址

如何解决《获取本地IP地址》经验,为你挑选了10个好方法。

在互联网上有几个地方向您展示如何获得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地址.



1> Mrchief..:

获取本地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虚拟盒,genymotion等东西将无法工作.
@John AddressFamily.InterNetwork是IP v4和AddressFamily.InterNetworkV6是IP v6
同意PaulEffect.这种方法不仅对多个网卡不利,而且也不区分IP v6和IP v4地址.
您似乎正在使用VMWare或其他虚拟化软件.OP没有要求这样做,所以我认为由于这一点投票有点苛刻.如果您有VMWare或多个NIC,其他一些答案已经提供了线索.

2> Mr.Wang from..:

当本地计算机上有多个IP地址时,有一种更准确的方法.ConnectUDP套接字并读取其本地端点:

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套接字API(UDP"连接"状态的副作用)的一个完整特征,它可以在Windows 和Linux中跨版本和发行版可靠地工作.

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


没有网络连接 - 无论如何你没有IP地址.因此,代码仍然保持有效,尽管为了处理这种情况而添加try..catch是谨慎的,如果抛出SocketException则返回类似"127.0.0.1"的内容.
该解决方案的工作速度比接受的答案快4倍(由Mrchief提供).这应该是真正的答案
这是满足我需求的最佳解决方案.在我的情况下,我有很多网卡和一些无线连接.我需要根据激活的连接获取首选IP地址.
@PatrickSteele,是的,它返回特定目标的首选出站IP地址.如果你想获得你的局域网IP地址,尝试从你的局域网指示目标是一些IP

3> Pure.Krome..:

重构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);
}

:)


@KeenoraFluffball - 这个给你第一个,而这个给你最后一个(反之亦然,取决于列表的构造方式).无论哪种方式,两者都不对 - 如果给你的IP地址超过1个,你需要知道你正在使用哪个网络.采取第一个或最后一个猜测不是正确的解决方案.

4> compman2408..:

我知道这可能会踢死马,但也许这可以帮助别人.我已经到处寻找一种方法来查找我的本地IP地址,但我发现它在任何地方都说使用:

Dns.GetHostEntry(Dns.GetHostName());

我根本不喜欢这个,因为它只是获取分配给您的计算机的所有地址.如果您有多个网络接口(几乎所有计算机现在都可以使用这些接口),您不知道哪个地址与哪个网络接口有关.在做了一堆研究后,我创建了一个函数来使用NetworkInterface类并从中提取信息.通过这种方式,我可以分辨出它是什么类型的接口(以太网,无线,环回,隧道等),它是否处于活动状态,以及更多的SOOO.

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 ipAddrList = new List();
    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地址.我也使用类似的方法.

5> Gerardo H..:

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

internal static string GetLocalIPv4(NetworkInterfaceType _type)
{
    string output = "";
    foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
        {
            IPInterfaceProperties adapterProperties = item.GetIPProperties();

            if (adapterProperties.GatewayAddresses.FirstOrDefault() != null)
            {
                foreach (UnicastIPAddressInformation ip in adapterProperties.UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        output = ip.Address.ToString();
                    }
                }
            }
        }
    }

    return output;
}

更改:我正在从分配了网关IP的适配器中检索IP.


有相同的问题,如它派生的代码:它只返回一个IP,一个来自许多的随机IP - 这不一定是你需要的.它赢得了http://www.ademiller.com/blogs/tech/2008/06/it-works-on-my-machine-award/

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()
        : "";
}



7> Kapé..:

我认为使用LinQ更容易:

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


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

8> Stajs..:

笑了一下,以为我会尝试使用新的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)。



9> Jordan Train..:

@mrcheif I found this answer today and it was very useful although it did return a wrong IP (not due to the code not working) but it gave the wrong internetwork IP when you have such things as Himachi running.

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个范围,都与该范围不同)的正确测试,而且很可能是公司网络范围,因此“本地”范围不是那么多。

10> Amirhossein ..:

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

public static List 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();
}

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有