获取本地IP地址

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

704708 次浏览

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

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

:)

@mrcheif我今天找到了这个答案,这是非常有用的,虽然它确实返回了一个错误的IP(不是由于代码不工作),但它给出了错误的互联网IP,当你有这样的东西,如Himachi运行。

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

我认为使用LINQ更容易:

Dns.GetHostEntry(Dns.GetHostName())
.AddressList
.First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
.ToString()
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();

我知道这可能是白费力气,但也许这能帮到别人。我到处寻找一种方法来找到我的本地IP地址,但我发现到处都说要使用:

Dns.GetHostEntry(Dns.GetHostName());

我一点也不喜欢这个,因为它只会获取分配给你电脑的所有地址。如果你有多个网络接口(现在几乎所有的计算机都有),你不知道哪个地址对应哪个网络接口。在做了大量的研究之后,我创建了一个函数来使用NetworkInterface类并从中提取信息。通过这种方式,我可以知道它是什么类型的接口(以太网、无线、环回、隧道等),它是否处于活动状态,等等。

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

当本地机器上有多个可用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套接字API的一个整体特征(UDP“连接”状态的副作用),在Windows 和Linux跨版本和发行版中可靠地工作。

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

下面是一个修改后的版本(来自compman2408的版本),它对我来说很有效:

    internal static string GetLocalIPv4(NetworkInterfaceType _type)
{  // Checks your IP adress from the local network connected to a gateway. This to avoid issues with double network cards
string output = "";  // default output
foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) // Iterate over each network interface
{  // Find the network interface which has been provided in the arguments, break the loop if found
if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
{   // Fetch the properties of this adapter
IPInterfaceProperties adapterProperties = item.GetIPProperties();
// Check if the gateway adress exist, if not its most likley a virtual network or smth
if (adapterProperties.GatewayAddresses.FirstOrDefault() != null)
{   // Iterate over each available unicast adresses
foreach (UnicastIPAddressInformation ip in adapterProperties.UnicastAddresses)
{   // If the IP is a local IPv4 adress
if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{   // we got a match!
output = ip.Address.ToString();
break;  // break the loop!!
}
}
}
}
// Check if we got a result if so break this method
if (output != "") { break; }
}
// Return results
return output;
}

你可以像这样调用这个方法:

GetLocalIPv4(NetworkInterfaceType.Ethernet);
更改:我正在从一个适配器中检索IP,该适配器已分配给它一个网关IP。 第二个变化:我添加了文档字符串和break语句,以使该方法更有效。< / p >

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

如果您有运营商级NAT,并且想与同一运营商的其他客户通信,该怎么办?在一般情况下,您永远无法确定,因为在每次NAT转换时可能会出现不同的主机名。

只是我使用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;
}

为了搞笑,我想我应该尝试使用新的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)。

前提条件:你必须添加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));

这是我发现的最好的代码,以获得当前的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()
: "";
}

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

过时了,这对我有用

public static IPAddress GetIPAddress()
{
IPAddress ip = Dns.GetHostAddresses(Dns.GetHostName()).Where(address =>
address.AddressFamily == AddressFamily.InterNetwork).First();
return 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;
}

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

使用一个或多个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;
}

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

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

希望对你有所帮助。

这将从两个单独的列表(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());
}

已经有很多答案了,但我还是贡献我的一个:

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"));

注意:从last开始搜索,因为它在一些接口添加到设备后仍然有效,如MobileHotspot,VPN或其他花哨的虚拟适配器。

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

enter image description here

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

使用这些:

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.AsEnumerable().Where(
ip=>ip.AddressFamily.Equals(AddressFamily.InterNetwork)
).FirstOrDefault().ToString()