Как разрешить адреса и информацию о портах из случая перечисления NWEndpoint.service (если возможно)

В настоящее время я использую NetServiceBrowser найти службы Bonjour и разрешить соответствующие адреса и порт.

Пытаясь упростить свой код, я наткнулся на NWBrowser который, кажется, предоставляет очень простой интерфейс для работы с обнаружением Bonjour.

Тем не менее browseResultsChangedHandler отправляет обратно результаты и изменения, которые содержат конечную точку enum case service. Я пытаюсь получить информацию об адресе и порте из результатов, но, похоже,NWEndpoint должен быть перечислимого типа.hostPort.

В идеале я бы использовал конечную точку для подключения к серверам, используя NWConnectionоднако я использую другую библиотеку, которая не обрабатывает NWEndpoint прямо.

Существуют ли (простые) способы получения адресов и информации о портах из NWEndpoint.service результат?

import Foundation
import Network

let browser = NWBrowser(for: .bonjour(type: "_http._tcp", domain: ""), using: NWParameters())

browser.browseResultsChangedHandler = { (results, changes) in
    print("Results:")

    for result in results
    {
        if case .service(let service) = result.endpoint
        {
            debugPrint(service)
        }
        else
        {
            assert(false, "This nevers gets executed")
        }
    }

    print("Changes:")

    for change in changes
    {
        if case .added(let added) = change
        {
            if case .service(let service) = added.endpoint
            {
                debugPrint(service)
            }
            else
            {
                assert(false, "This nevers gets executed")
            }
        }
    }
}

browser.start(queue: DispatchQueue.main)

sleep(3)

1 ответ

Решение

Это возможно.

Во-первых, вы не должны пытаться получить хост и порт службы до тех пор, пока пользователь не решит подключиться к ней - в большинстве приложений вы должны хранить только ссылку на объект службы, поскольку Bonjour позволяет хосту и порту службы подключаться к ней. изменять. Из концепции Bonjour:

Кроме того, службы не привязаны к конкретным IP-адресам или даже именам хостов. […] Если клиенты сохраняют имя хоста (как в большинстве случаев они хранят сейчас), они не смогут подключиться, если служба переместится на другой хост.

Bonjour придерживается сервис-ориентированного взгляда. Запросы выполняются в соответствии с типом необходимых услуг, а не с хостами, которые их предоставляют. Приложения хранят имена экземпляров службы, а не адреса, поэтому, если IP-адрес, номер порта или даже имя хоста изменились, приложение все равно может подключиться. Сосредоточение внимания на услугах, а не на устройствах, делает работу пользователя в Интернете более полезной и беспроблемной.

Это снижает шум DNS в вашей сети и является основой конструкции Bonjour. Это означает, что все мои следующие предложения не должны происходить в вашем browseResultsChangedHandler.

Официально рекомендуемый способ использования NWBrowser кажется, чтобы открыть NWConnectionк службе и используйте это вместо извлечения адреса и порта и подключения вручную. Вы можете открыть соединение, и сетевая структура будет обрабатывать разрешение фактического хоста / порта и подключение к службе.

      let connection = NWConnection(to: service.endpoint, using: .tcp)

connection.stateUpdateHandler = { state in
    switch state {
    case .ready:
        if let innerEndpoint = connection.currentPath?.remoteEndpoint,
           case .hostPort(let host, let port) = innerEndpoint {
            print("Connected to", "\(host):\(port)") // Here, I have the host/port information
        }
    default:
        break
    }
}
connection.start(queue: .global())

Если вы не можете использовать это соединение с сетевой структурой, я предполагаю, что вы могли бы затем закрыть соединение (возможно, вам нужно подождать, пока TCP перестанет использовать порт) и использовать его в своих целях.

Вы также можете использовать устаревший NetService api для разрешения службы (хотя я лично не получил это для работы с экземпляром, созданным вручную) или DNSServiceResolve.

В есть гораздо больше информации от официального представителя этой ветке форума разработчиков AppleApple.

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