#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. Это не идеальное решение, которое я искал, но из того, что вы говорите, нет определенного способа его реализации. Отметит ваш ответ как принятый. Спасибо за информацию.