获取本地IP地址

Ton*_*Nam 269 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();
Run Code Online (Sandbox Code Playgroud)

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

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

Mrc*_*ief 427

获取本地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!");
}
Run Code Online (Sandbox Code Playgroud)

检查您是否已连接:

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

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

Mr.*_*oor 199

当本地计算机上有多个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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 没有网络连接 - 无论如何你没有IP地址.因此,代码仍然保持有效,尽管为了处理这种情况而添加try..catch是谨慎的,如果抛出SocketException则返回类似"127.0.0.1"的内容. (10认同)
  • 该解决方案的工作速度比接受的答案快4倍(由Mrchief提供).这应该是真正的答案 (6认同)
  • 这是满足我需求的最佳解决方案.在我的情况下,我有很多网卡和一些无线连接.我需要根据激活的连接获取首选IP地址. (4认同)
  • 此方法适用于具有 dotnet 核心的 mac,而目前已接受的答案不适用。 (3认同)
  • @PatrickSteele,是的,它返回特定目标的首选出站IP地址.如果你想获得你的局域网IP地址,尝试从你的局域网指示目标是一些IP (2认同)
  • &gt;&gt; 您现在已完全断开与互联网的连接。@AlexC,此方法返回本地 IP 地址,该地址在访问特定远程 IP 地址时应该使用。根据您的描述,您需要的不是`GetLocalIP()`,您需要的是`IsSomethingReachable()` (2认同)
  • 不过,此方法需要有互联网连接......在您不知道谁是网关或要连接到什么的本地网络中,您会使用什么来代替 Google 的“8.8.8.8”? (2认同)

Pur*_*ome 105

重构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);
}
Run Code Online (Sandbox Code Playgroud)

:)

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

com*_*408 99

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

Dns.GetHostEntry(Dns.GetHostName());
Run Code Online (Sandbox Code Playgroud)

我根本不喜欢这个,因为它只是获取分配给您的计算机的所有地址.如果您有多个网络接口(几乎所有计算机现在都可以使用这些接口),您不知道哪个地址与哪个网络接口有关.在做了一堆研究后,我创建了一个函数来使用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;
}
Run Code Online (Sandbox Code Playgroud)

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

GetLocalIPv4(NetworkInterfaceType.Ethernet);
Run Code Online (Sandbox Code Playgroud)

或者您的无线接口:

GetLocalIPv4(NetworkInterfaceType.Wireless80211);
Run Code Online (Sandbox Code Playgroud)

如果您尝试获取无线接口的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();
}
Run Code Online (Sandbox Code Playgroud)

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

GetLocalIPv4(NetworkInterfaceType.Ethernet).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

  • 这是一个更好的解决方案,因为在很多地方没有DNS可用性,并且接口可以有多个ip地址.我也使用类似的方法. (5认同)

Ger*_*o H 28

这是一个修改后的版本(来自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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 有相同的问题,如它派生的代码:它只返回一个IP,一个来自许多的随机IP - 这不一定是你需要的.它赢得了http://www.ademiller.com/blogs/tech/2008/06/it-works-on-my-machine-award/ (4认同)
  • 巧妙的解决方案。我现在在用这个。 (2认同)

小智 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()
        : "";
}
Run Code Online (Sandbox Code Playgroud)


Kap*_*apé 11

我认为使用LinQ更容易:

Dns.GetHostEntry(Dns.GetHostName())
   .AddressList
   .First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
   .ToString()
Run Code Online (Sandbox Code Playgroud)

  • Mark,即使是这种简短的形式,该语句确实使用了带有方法(lambda)语法的LINQ-to-objects.查询语法只是语法糖,它被编译成一系列IEnumerable扩展方法调用,这就是LINQ-to-objects.来源:撰写了一篇LINQ-to-SQL提供程序和一系列有关该主题的文章. (15认同)
  • 这不是LINQ,那是扩展方法和lambdas.有区别. (13认同)
  • @Mark - 如果你不添加"using System.Linq;" 但是你不能使用"First"扩展方法 (8认同)
  • 这是因为扩展方法位于System.Linq命名空间中的Enumerable类中.它仍然不是LINQ. (4认同)
  • [方法语法仍然是 LINQ。](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq)。 (3认同)

Sta*_*ajs 8

笑了一下,以为我会尝试使用新的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;
}
Run Code Online (Sandbox Code Playgroud)

逻辑礼貌Gerardo H(并通过引用compman2408)。


Sha*_*waj 7

使用一个或多个 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;
    }
Run Code Online (Sandbox Code Playgroud)


Jor*_*nor 5

@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;
}
Run Code Online (Sandbox Code Playgroud)

  • 您是说Logmein Hamachi吗?这是一个VPN解决方案,它会修补网络堆栈。另外,作为VPN,在连接时返回VPN分配的IP是合理的(这只是我的猜测)。 (2认同)
  • 完全不可靠。“ 192.0.0.0/8”不仅不是对私有IP地址(有3个范围,都与该范围不同)的正确测试,而且很可能是公司网络范围,因此“本地”范围不是那么多。 (2认同)

小智 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;
}
Run Code Online (Sandbox Code Playgroud)


Ami*_*ari 5

使用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();
}
Run Code Online (Sandbox Code Playgroud)