C# — Поиск локального IP-адреса моей машины, а не виртуальной машины

#c# #tcp #ip

Вопрос:

На моей машине установлена виртуальная машина VirtualBox, и поэтому для нее появляется адаптер Ethernet. Я перечисляю список IP-адресов моей машины по следующему адресу:

        public string GetLocalIpAddress()
       {
            try
            {
                string strHostName = Dns.GetHostName();

                // Then using host name, get the IP address list..
                IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);

                foreach (IPAddress ip in ipEntry.AddressList)
                {
                    if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        return string.Format("({0})", ip.ToString());
                    }
                }
            }
            catch(Exception e)
            {
                Global.ApplicationLog.AddApplicationLog(EnumAppEventTypes.SYSTEM_ERROR, e.ToString());
            }

            return "";
        }
 

Моя проблема в том, что адаптер Ethernet виртуальной машины также зависит от состояния:

 if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
 

Есть ли способ выбрать локальный ip-адрес моей машины и игнорировать адрес моей виртуальной машины?

Ответ №1:

Я уточняю ответ Андрея Арха, так как IP-адрес, сообщаемый GatewayAddresses, также может быть «0.0.0.0», а не просто нулевым:

     public static string GetPhysicalIPAdress()
    {
        foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
        {
            var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
            if (addr != null amp;amp; !addr.Address.ToString().Equals("0.0.0.0"))
            {
                if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                {
                    foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            return ip.Address.ToString();
                        }
                    }
                }
            }
        }
        return String.Empty;
    }
 

Комментарии:

1. Это не работает, если шлюза нет, но адрес по-прежнему физический.

Ответ №2:

Используйте WMI и проверьте свойство ConnectorPresent для физического устройства.

 public static string GetPhysicalIPAdress()
{
    foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (ConnectorPresent(ni))
        {
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
            {
                foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        return ip.Address.ToString();
                    }
                }
            }
        }
    }
    return string.Empty;
}

private static bool ConnectorPresent(NetworkInterface ni)
{
    ManagementScope scope = new ManagementScope(@"\localhostrootStandardCimv2");
    ObjectQuery query = new ObjectQuery(String.Format(
        @"SELECT * FROM MSFT_NetAdapter WHERE ConnectorPresent = True AND DeviceID = '{0}'", ni.Id));
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
    ManagementObjectCollection result = searcher.Get();
    return result.Count > 0;
}
 

Комментарии:

1. Это сработало для меня с одной поправкой: я также проверил, что ni. OperationalStatus == OperationalStatus.Up. Без этой дополнительной проверки он возвращал интерфейсы, которые на самом деле были отключены.

Ответ №3:

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

 foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
    var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
    if (addr != null)
    {
        if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
        {
            Console.WriteLine(ni.Name);
            foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
            {
                if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    Console.WriteLine(ip.Address.ToString());
                }
            }
        }
    }
}
 

Ответ №4:

Вы можете игнорировать адаптер Ethernet по его имени. Поскольку адаптер Ethernet виртуальной машины представлен действительным драйвером сетевой карты, он полностью эквивалентен физической сетевой карте вашей машины с точки зрения операционной системы.

Комментарии:

1. К сожалению, класс IPAddress, похоже, не сохраняет имя адаптера ethernet, поэтому я не могу удалить адаптер ethernet виртуальной машины с помощью этого метода.

2. Да, возможно, вам придется изменить свой подход, используя NetworkInterface. Метод GetAllNetworkInterfaces (). Он вернет все интерфейсы, а затем вы сможете перечислить все доступные IP-адреса для каждого интерфейса.

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

4. Ну, нет гарантированного способа отличить виртуальную сетевую карту от физической. Они оба представлены реальными водителями и не носят никаких значков с надписью «Я виртуальный». Таким образом, единственный способ разделения ваших сетевых карт-это попросить пользователя пометить виртуальные сетевые карты (тогда вы можете использовать идентификаторы сетевых карт, чтобы отличать их друг от друга).

5. Это не идеальное решение, которое я искал, но из того, что вы говорите, нет определенного способа его реализации. Отметит ваш ответ как принятый. Спасибо за информацию.