Swift Network.framework: получите NWInterface для интерфейса Ethernet без IP-подключения
На переговорах о "достижениях в области сетевых технологий" на WWDC2019 был приведен пример использования NWEthernetChannel
для мониторинга пользовательского (не IP) протокола. Это для MacOS.
import Foundation
import Network
let path = NWPathMonitor(requiredInterfaceType: .wiredEthernet).currentPath
guard let interface = path.availableInterfaces.first else {
fatalError("not connected to Internet")
}
let channel = NWEthernetChannel(on: interface, etherType: 0xB26E)
Для моего приложения мне нужно использовать NWEthernetChannel
для мониторинга пользовательского протокола (на самом деле протокола обнаружения Cisco и / или протокола обнаружения канального уровня) на канале Ethernet, который не имеет возможности подключения к Интернету по IP (но имеет физическое соединение с коммутатором). NWPath, похоже, дает мне структуру NWInterface, только если это действительный путь к Интернету.
Как мне получить список NWInterface
Structs на Mac без действительного пути в Интернет?
В моем конкретном случае использования меня интересует только .wiredEthernet.
Что-то столь же простое, как получить полный набор всех NWInterfaces
на коробке хватило бы, но пока единственный способ "продать" NWInterfaces
Я нашел это с NWPathMonitor
, который, похоже, требует подключения по IP.
1 ответ
Вы можете получить NWIntferface
если вы знаете соответствующее ему имя BSD. ДокументацияIPv4Address.init(_:)
говорит, что вы можете указать имя интерфейса после IP-адреса, разделенного %
.
/// Create an IP address from an address literal string.
/// If the string contains '%' to indicate an interface, the interface will be
/// associated with the address, such as "::1%lo0" being associated with the loopback
/// interface.
/// This function does not perform host name to address resolution. This is the same as calling getaddrinfo
/// and using AI_NUMERICHOST.
Вы можете найти эту документацию только в созданном быстром интерфейсе, но не на веб-сайте.
В SystemConfiguration
framework предоставляет функциональные возможности для получения списка всех интерфейсов с соответствующими именами BSD.
import Foundation
import Network
import SystemConfiguration
// get all interfaces
let interfaces = SCNetworkInterfaceCopyAll() as? Array<SCNetworkInterface> ?? []
// convert to NWInterface
let nwInterfaces = interfaces.compactMap { interface -> NWInterface? in
guard let bsdName = SCNetworkInterfaceGetBSDName(interface) else { return nil }
return IPv4Address("127.0.0.1%\(bsdName)")?.interface
}
print(interfaces)
Это работает хорошо, но похоже на обходной путь. Я бы хотел, чтобы Network.framework предоставил лучший вариант для получения всех интерфейсов.