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


当前回答

当本地机器上有多个可用ip地址时,有一种更准确的方法。连接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();
}

Connect on a UDP socket has the following effect: it sets the destination for Send/Recv, discards all packets from other addresses, and - which is what we use - transfers the socket into "connected" state, settings its appropriate fields. This includes checking the existence of the route to the destination according to the system's routing table and setting the local endpoint accordingly. The last part seems to be undocumented officially but it looks like an integral trait of Berkeley sockets API (a side effect of UDP "connected" state) that works reliably in both Windows and Linux across versions and distributions.

因此,此方法将提供用于连接到指定远程主机的本地地址。没有建立真正的连接,因此指定的远端ip不可达。

其他回答

用Linq更新Mrchief的答案,我们会有:

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

使用这些:

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

Dns.GetHostEntry(Dns.GetHostName()).AddressList[1].MapToIPv4() //returns 192.168.14.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;
}

此外,只是获取客户端Ip的简单代码:

        public static string getclientIP()
        {
            var HostIP = HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : "";
            return HostIP;
        }

希望对你有所帮助。