如何确定本地主机的IPv4地址?

30

我如何从Dns.GetHostAddresses()中获取仅限Internet Protocol version 4地址?我已经有下面的代码,但它给出IPv4和IPv6地址。我需要让它适用于具有多个IPv4地址的盒子。

IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
private void get_IPs()
    {
        foreach (IPAddress a in localIPs)
        {
           server_ip = server_ip + a.ToString() + "/";
        }
    }
11个回答

36

来自我的博客

/// <summary> 
/// This utility function displays all the IP (v4, not v6) addresses of the local computer. 
/// </summary> 
public static void DisplayIPAddresses() 
{ 
    StringBuilder sb = new StringBuilder(); 

    // 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(); 

        // 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; 

            sb.AppendLine(address.Address.ToString() + " (" + network.Name + ")"); 
        } 
    } 

    MessageBox.Show(sb.ToString()); 
}

特别是,我不推荐使用Dns.GetHostAddresses(Dns.GetHostName());,无论这行代码在各种文章和博客中多么受欢迎。


2
我之前在使用 DNS 时一直无法得到正确的结果,但这个方法给了我想要的答案。谢谢。 - Tsukasa
1
之前在 Azure 托管的网站遇到了一些问题。但是这个方法运行得非常好,与你提到的 Dns.GetHostAddress 方法相比。 - Tudor Carean

28

在你的代码中添加类似以下内容的东西

  if( IPAddress.Parse(a).AddressFamily == AddressFamily.InterNetwork )
  // IPv4 address

foreach (IPAddress a in localIPs) { if (a.IsIPv6LinkLocal == false) { server_ip = server_ip + a.ToString() + "/"; } } - John Ryann
1
问题在于我从这个方法中收到了一个169.254.x.x的地址。 - Brain2000

12

这是我使用的一个函数:

public static string GetIP4Address()
{
    string IP4Address = String.Empty;

    foreach (IPAddress IPA in Dns.GetHostAddresses(Dns.GetHostName()))
    {
        if (IPA.AddressFamily == AddressFamily.InterNetwork)
        {
            IP4Address = IPA.ToString();
            break;
        }
    }

    return IP4Address;
}
作为一个可枚举对象:
public static IEnumerable<string> GetIP4Addresses()
{
    return Dns.GetHostAddresses(Dns.GetHostName())
        .Where(IPA => IPA.AddressFamily == AddressFamily.InterNetwork)
        .Select(x => x.ToString());
}

1
我不建议使用字符串进行比较,因为这需要通过反射查找枚举值并执行字符串比较。特别是因为您可以毫无问题地与枚举AddressFamily.InterNetwork进行比较。 - Alex
该函数返回一个地址,但问题说明它必须支持具有多个IPv4地址的主机。 - Greg Bacon

7

Linq使用起来非常简洁而且方便

IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName()).Where(a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToArray();

4

根据MSDN关于Dns.GetHostAddresses的说明,当传入空字符串作为主机名时,此方法将返回除Windows Server 2003之外的所有操作系统的本地主机的IPv4地址;对于Windows Server 2003,将返回本地主机的IPv4和IPv6地址。

如果本地计算机未安装IPv6,则从GetHostAddresses方法的结果中过滤掉IPv6地址。因此,如果hostNameOrAddress参数只有IPv6结果可用,则可能会返回一个空的IPAddress实例。

因此,您可以使用此方法进行尝试和解析

IPAddress.TryParse

接着检查AddressFamily属性,它会返回IPv4的值System.Net.Sockets.AddressFamily.InterNetwork或IPv6的值System.Net.Sockets.AddressFamily.InterNetworkV6。

string input = "192.168.0.10";

IPAddress address;
if (IPAddress.TryParse(input, out address))
{
    switch (address.AddressFamily)
    {
        case System.Net.Sockets.AddressFamily.InterNetwork:
            // we have IPv4
            break;
        case System.Net.Sockets.AddressFamily.InterNetworkV6:
            // we have IPv6
            break;
        default:
            // do something else
            break;
    }
}

4

请写出 locaIPs.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork)

该代码意为筛选出本地IP地址中的IPv4地址。


1
我使用了以

开始的答案。

/// <summary> and it mostly worked:
//for some reason Visual Studio 2010 did not understand AddressFamily.Inernetwork
    if (address.Address.AddressFamily != AddressFamily.InterNetwork) 

我不得不使用:

if(address.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)

但实际上我使用了:

if(!address.Address.AddressFamily.Equals(System.Net.Sockets.AddressFamily.InterNetwork))

Also, I added:

if (network.OperationalStatus != OperationalStatus.Up)
                continue;

因为有一些网络根本不起作用,也不应该存在,我确实看到它们在注册表中。---Alvin


0

这是我的代码。 并且可以在许多局域网卡上找到它。

private string GetLocalIpAddress()
{
    string localIpAddress = string.Empty;
    NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();

    foreach (NetworkInterface nic in nics)
    {
        if (nic.OperationalStatus != OperationalStatus.Up)
        {
            continue;
        }

        IPv4InterfaceStatistics adapterStat = (nic).GetIPv4Statistics();
        UnicastIPAddressInformationCollection uniCast = (nic).GetIPProperties().UnicastAddresses;

        if (uniCast != null)
        {
            foreach (UnicastIPAddressInformation uni in uniCast)
            {
                if (adapterStat.UnicastPacketsReceived > 0
                    && adapterStat.UnicastPacketsSent > 0
                    && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)
                {
                    if (uni.Address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        localIpAddress = nic.GetIPProperties().UnicastAddresses[0].Address.ToString();

                        break;
                    }
                }
            }
        }
    }

    return localIpAddress;
}

0

对我来说,更为简洁的解决方案是:

 public static string GetLocalIP() 
        {
            string ipv4Address = String.Empty;

            foreach (IPAddress currentIPAddress in Dns.GetHostAddresses(Dns.GetHostName()))
            {
                if (currentIPAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    ipv4Address = currentIPAddress.ToString();
                    break;
                }
            }

            return ipv4Address;
        }

该函数返回一个地址,但问题说明它必须支持具有多个IPv4地址的主机。 - Greg Bacon

0

以下是使用for循环查找第一个连接的IPv4地址的代码:

        IPAddress ipAddress = null;
        IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());           

        for (int i=0 ; i<localIPs.Length ; i++)
        {
            if (localIPs[i].AddressFamily == AddressFamily.InterNetwork)
            {
                ipAddress = localIPs[i];
                break;
            }                
        }

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