获取本地IP地址

时间:2011-07-23 20:20:49

标签: c# networking

在互联网上有几个地方可以告诉你如何获得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地址。

27 个答案:

答案 0 :(得分:395)

获取本地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();

答案 1 :(得分:175)

当本地计算机上有多个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();
}
UDP套接字上的

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

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

答案 2 :(得分:103)

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

:)

答案 3 :(得分:90)

我知道这可能会踢死马,但也许这可以帮助别人。我到处寻找一种方法来查找我的本地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<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();

答案 4 :(得分:23)

这是一个修改后的版本(来自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。

答案 5 :(得分:18)

这是我发现获取当前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()
        : "";
}

答案 6 :(得分:8)

我认为使用LinQ更容易:

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

答案 7 :(得分:4)

@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;
}

答案 8 :(得分:4)

经过一个或多个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;
    }

答案 9 :(得分:4)

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

答案 10 :(得分:3)

使用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();
}

答案 11 :(得分:2)

先决条件:您必须添加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));

答案 12 :(得分:1)

使用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 :(得分:1)

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

如果您拥有运营商级NAT,并希望与同一运营商的其他客户进行通信,该怎么办?在一般情况下,您永远不会确定,因为在每次NAT转换时,您可能会显示不同的主机名。

答案 14 :(得分: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();

答案 15 :(得分:1)

已过时,这对我有用

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

答案 16 :(得分:1)

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

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

答案 17 :(得分:1)

我也在努力获得正确的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);

答案 18 :(得分:1)

这将从任何接口返回地址,这些接口的网关地址和单播地址在两个单独的列表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());
}

答案 19 :(得分:0)

此外,还有用于获取客户端IP的简单代码:

inputContainerStyle={{
                    borderColor: 'transparent'
                }}

希望对您有帮助。

答案 20 :(得分:0)

已经有很多答案了,但我仍然是我的一个:

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或其他精美的虚拟适配器)后,它仍然可以工作。

答案 21 :(得分:0)

修改了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"}");
    }
}

答案 22 :(得分:0)

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

答案 23 :(得分:0)

使用这些:

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方法的漂亮解决方案的能力,例如以及更多代码)

答案 24 :(得分:-1)

Dns.GetHostEntry(Dns.GetHostName()).AddressList[1]

一行代码:D

答案 25 :(得分:-1)

Dns.GetHostEntry(Dns.GetHostName()).AddressList[1].MapToIPv4() //returns 192.168.14.1

enter image description here

答案 26 :(得分:-3)

如果您有虚拟机或额外的网卡,则地址列表中可能还有其他值。我的建议是检查地址列表和打印的条目是否合适。在我的情况下,条目3是我机器的ipv4地址

IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[3];
string ip = ipAddr.ToString();

不要忘记添加using System.Net;