Получить локальный IP-адрес - PullRequest
245 голосов
/ 24 июля 2011

В интернете есть несколько мест, которые показывают вам, как получить 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 #, и если это так, то получить IP-адрес локальной сети.

Ответы [ 20 ]

400 голосов
/ 24 июля 2011

Чтобы получить локальный 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();

179 голосов
/ 09 декабря 2014

Существует более точный способ, когда на локальном компьютере доступны несколько 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();
}

Connect на сокете UDP имеет следующий эффект: он устанавливает пункт назначения для Send / Recv, отбрасывает все пакеты с других адресов и - что мы используем - передает сокет в «подключенный» состояние, настройки соответствующих полей. Это включает в себя проверку наличия маршрута к пункту назначения в соответствии с таблицей маршрутизации системы и соответствующей настройкой локальной конечной точки. Последняя часть, кажется, официально не документирована, но выглядит как неотъемлемая черта API сокетов Беркли (побочный эффект состояния «подключен» UDP), который надежно работает как в Windows , так и в Linux в разных версиях и дистрибутивах.

Итак, этот метод даст локальный адрес, который будет использоваться для подключения к указанному удаленному хосту. Реальное соединение не установлено, поэтому указанный удаленный ip может быть недоступен.

104 голосов
/ 22 августа 2011

Рефакторинг кода 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);
}

:)

91 голосов
/ 18 июля 2014

Я знаю, что это может ударить мертвую лошадь, но, возможно, это может кому-то помочь. Я искал повсюду способ найти свой локальный IP-адрес, но везде, где я нахожу, написано:

Dns.GetHostEntry(Dns.GetHostName());

Мне это совсем не нравится, потому что он просто получает все адреса, назначенные вашему компьютеру. Если у вас есть несколько сетевых интерфейсов (что почти все компьютеры делают в настоящее время), вы не знаете, какой адрес соответствует какому сетевому интерфейсу. Проведя кучу исследований, я создал функцию для использования класса NetworkInterface и извлечения из него информации. Таким образом, я могу сказать, какой это тип интерфейса (Ethernet, беспроводной, шлейф, туннель и т. Д.), Активен он или нет, и 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-адрес вызова сетевого интерфейса Ethernet:

GetLocalIPv4(NetworkInterfaceType.Ethernet);

Или ваш беспроводной интерфейс:

GetLocalIPv4(NetworkInterfaceType.Wireless80211);

Если вы попытаетесь получить IPv4-адрес для беспроводного интерфейса, но на вашем компьютере не установлена ​​беспроводная карта, он просто вернет пустую строку. То же самое с интерфейсом Ethernet.

Надеюсь, это кому-нибудь поможет! : -)

EDIT:

Было отмечено (спасибо @NasBanov), что, хотя эта функция позволяет извлекать IP-адрес гораздо лучше, чем при использовании Dns.GetHostEntry(Dns.GetHostName()), она не очень хорошо поддерживает несколько интерфейсов одного типа или нескольких 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();
23 голосов
/ 20 февраля 2015

Вот измененная версия (от 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.

18 голосов
/ 10 ноября 2016

Это лучший код, который я нашел для получения текущего 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()
        : "";
}
8 голосов
/ 25 марта 2014

Я думаю, что использовать LinQ проще:

Dns.GetHostEntry(Dns.GetHostName())
   .AddressList
   .First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
   .ToString()
4 голосов
/ 23 ноября 2012

@ 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;
}
4 голосов
/ 05 октября 2018

Протестировано с одной или несколькими сетевыми картами и виртуальными машинами

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;
    }
4 голосов
/ 10 февраля 2016

Для смеха подумал, что я попытаюсь получить один оператор LINQ, используя новый условно-нулевой оператор C # 6. Выглядит довольно сумасшедшим и, вероятно, ужасно неэффективно, но это работает.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...