Get local IP address

2019-01-01 03:21发布

问题:

In the internet there are several places that show you how to get an IP address. And a lot of them look like this example:

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

With this example I get several IP addresses, but I\'m only interested in getting the one that the router assigns to the computer running the program: the IP that I would give to someone if he wishes to access a shared folder in my computer for instance.

If I am not connected to a network and I am connected to the internet directly via a modem with no router then I would like to get an error. How can I see if my computer is connected to a network with C# and if it is then to get the LAN IP address.

回答1:

To get local Ip Address:

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!\");
}

To check if you\'re connected or not:

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



回答2:

There is a more accurate way when there are multi ip addresses available on local machine. Connect a UDP socket and read its local endpoint:

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.

So, this method will give the local address that would be used to connect to the specified remote host. There is no real connection established, hence the specified remote ip can be unreachable.



回答3:

Refactoring Mrcheif\'s code to leverage Linq (ie. .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);
}

:)



回答4:

I know this may be kicking a dead horse, but maybe this can help someone. I have looked all over the place for a way to find my local IP address, but everywhere I find it says to use:

Dns.GetHostEntry(Dns.GetHostName());

I don\'t like this at all because it just gets all the addresses assigned to your computer. If you have multiple network interfaces (which pretty much all computers do now-a-days) you have no idea which address goes with which network interface. After doing a bunch of research I created a function to use the NetworkInterface class and yank the information out of it. This way I can tell what type of interface it is (Ethernet, wireless, loopback, tunnel, etc.), whether it is active or not, and SOOO much more.

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

Now to get the IPv4 address of your Ethernet network interface call:

GetLocalIPv4(NetworkInterfaceType.Ethernet);

Or your Wireless interface:

GetLocalIPv4(NetworkInterfaceType.Wireless80211);

If you try to get an IPv4 address for a wireless interface, but your computer doesn\'t have a wireless card installed it will just return an empty string. Same thing with the Ethernet interface.

Hope this helps someone! :-)

EDIT:

It was pointed out (thanks @NasBanov) that even though this function goes about extracting the IP address in a much better way than using Dns.GetHostEntry(Dns.GetHostName()) it doesn\'t do very well at supporting multiple interfaces of the same type or multiple IP addresses on a single interface. It will only return a single IP address when there may be multiple addresses assigned. To return ALL of these assigned addresses you could simply manipulate the original function to always return an array instead of a single string. For example:

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

Now this function will return ALL assigned addresses for a specific interface type. Now to get just a single string, you could use the .FirstOrDefault() extension to return the first item in the array or, if it\'s empty, return an empty string.

GetLocalIPv4(NetworkInterfaceType.Ethernet).FirstOrDefault();


回答5:

Here is a modified version (from compman2408\'s one) which worked for me:

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

The change: I\'m retrieving the IP from an adapter which has a gateway IP assigned to it.



回答6:

This is the best code I found to get the current IP, avoiding get VMWare host or other invalid IP address.

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()
        : \"\";
}


回答7:

I think using LinQ is easier:

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


回答8:

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


回答9:

For a laugh, thought I\'d try and get a single LINQ statement by using the new C# 6 null-conditional operator. Looks pretty crazy and probably horribly inefficient, but it works.

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

Logic courtesy of Gerardo H (and by reference compman2408).



回答10:

Pre requisites: you have to add System.Data.Linq reference and refer it

using System.Linq;
string ipAddress =\"\";
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
ipAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork));


回答11:

Other way to get IP using linq expression:

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


回答12:

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


回答13:

Keep in mind, in the general case you could have multiple NAT translations going on, and multiple dns servers, each operating on different NAT translation levels.

What if you have carrier grade NAT, and want to communicate with other customers of the same carrier? In the general case you never know for sure because you might appear with different host names at every NAT translation.



回答14:

Obsolete gone, this works to me

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


回答15:

Updating Mrchief\'s answer with Linq, we will have:

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


回答16:

I also was struggling with obtaining the correct IP.

I tried a variety of the solutions here but none provided me the desired affect. Almost all of the conditional tests that was provided caused no address to be used.

This is what worked for me, hope it helps...

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


回答17:

Just an updated version of mine using 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;
}


回答18:

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

one line of code :D



回答19:

Tested with one or multiple LAN cards and Virtual machines

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


回答20:

If you have virtual machines or extra network cards there may be other values in addresslist. My suggestion is to check the entries of addresslist and print which is appropriate. In my case entry 3 was ipv4 address of my machine

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

Don\'t forget to add using System.Net;



回答21:

Here comes a fully functional and solid 1-liner for the local IP address-question. Made with the parallel execution language Dyalog APL. Interestingly, this minor piece of code supports 0, 1 or multiple IPv4 adapters - the result will just be an array with length 0, 1 or n of enclosed text vectors.

Mostly for your confusion, i guess :-)

#.Dns.(a.AddressFamily.(⎕THIS=InterNetwork)/a←(GetHostEntry GetHostName).AddressList).ToString

Returns (for this computer): 192.168.0.100 (<-- one-element boxed vector, the 1st element being a 13-character text vector)



标签: c# networking