Как программно получить список всех активных сетевых интерфейсов?

Моя цель - определить IP-адрес для Ethernet на устройстве. Но если предположить, что есть такие соединения, как WiFi и USB Ethernet, есть ли какой-то особый способ получить IP-адрес Ethernet?

В оболочке я бы сделал networksetup -listallhardwareports, что дало бы мне сопоставление аппаратного порта с устройством. Исходя из этого, я бы нашел устройство для аппаратного порта: Ethernet, а затем использовал структуру ifaddr, чтобы получить свой IP-адрес.

Я знаю часть ifaddr, подскажите, пожалуйста, как сделать первую часть программно. Кроме того, есть ли альтернативный подход?

Вы можете использовать scutilкоманду для вывода списка активных сетевых интерфейсов с их адресами IPv4 и 6:scutil --nwi

Ответы (2)

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

У меня есть MacBook Pro, у которого нет встроенного порта Ethernet, поэтому в своих примерах я буду использовать аппаратный порт: Wi-Fi, так как я тестировал это в обоих примерах ниже, и это сработало, однако вы можете изменить его на аппаратный порт . : Ethernet, если это то, что показывает вывод
networksetup -listallhardwareportsдля вас.

Если вы просто хотите вывести IP-адрес целевого устройства в stdout, используйте следующий пример:

$ ipconfig getifaddr $(networksetup -listallhardwareports | awk '/Hardware Port: Wi-Fi/{getline; print $2}')
192.168.1.100

Если вы хотите присвоить его переменной в скрипте , используйте следующий пример:

ipAddress="$(ipconfig getifaddr $(networksetup -listallhardwareports | awk '/Hardware Port: Wi-Fi/{getline; print $2}'))"

Объяснение:

Соответствующий вывод networksetup -listallhardwareportsдля моей системы:

Hardware Port: Wi-Fi
Device: en0
Ethernet Address: 28:cf:e3:10:a4:cd

(Примечание: это не мой реальный MAC-адрес)

Используя $(...)подстановку команд, чтобы иметь что-то для передачи, ipconfig getifaddr <args>я определяю имя устройства аппаратного порта с выводом networksetup -listallhardwareportsи передаю |его через awkкоторый ищет Hardware Port: Wi-Fiи использует get lineфункцию, которая читает следующую строку после совпадения и передается в print $2, который в Essence печатает вторую часть строки после match , которая в данном случае есть en0и передается ipconfig getifaddrв качестве аргумента в первом примере, например ipconfig getifaddr en0. Результатом которого является IP-адрес.

$(...)Во втором примере используется вторая подстановка команд вокруг сложной командной строки, используемой в stdoutпримере, чтобы присвоить ее переменной ipAddress при использовании в сценарии .

Примечание. Это действительно должно быть примером, поскольку я не закодировал его для учета отказа устройства. Другими словами, если у устройства нет IP-адреса, не будет вывода stdoutи ничего не будет назначено ipAddress переменной в скрипте . Хотя в скрипте можно закодировать, чтобы проверить, пуста ли ipAddress переменная , и действовать соответственно.

О, спасибо, но я ищу более основанное на syscall/C решение....
если вы знаете имя интерфейса, который вы можете использовать: `ipconfig getifaddr en0`

Используйте SCNetworkInterfaceCopyAll, чтобы получить список интерфейсов, затем отфильтруйте те, которые не возвращают Ethernet, с помощью SCNetworkInterfaceGetInterfaceType . Оттуда вы можете получить шлюз, маску и т. д. В питоне я использую для этого нетифейсы .

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