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 предоставил лучший вариант для получения всех интерфейсов.

Другие вопросы по тегам