swift - 如何从 NWEndpoint.service 枚举案例解析地址和端口信息(如果可能)

标签 swift macos bonjour dns-sd network-framework

目前我正在使用 NetServiceBrowser查找 Bonjour 服务并解析相应的地址和端口。

为了简化我的代码,我偶然发现了 NWBrowser它似乎提供了一个非常简单的界面来处理 Bonjour 发现。

然而,browseResultsChangedHandler发回包含枚举案例端点的结果和更改 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)

最佳答案

这个有可能。
首先,在用户实际选择连接之前,您不应尝试获取服务的主机和端口 - 在您的大多数应用程序中,您应该只存储对服务对象的引用,因为 Bonjour 允许服务的主机和端口改变。来自 Bonjour Concepts :

Additionally, services are not tied to specific IP addresses or even host names. […] If clients store the host name (as in most cases they now do), they will not be able to connect if the service moves to a different host.

Bonjour takes the service-oriented view. Queries are made according to the type of service needed, not the hosts providing them. Applications store service instance names, not addresses, so if the IP address, port number, or even host name has changed, the application can still connect. By concentrating on services rather than devices, the user’s browsing experience is made more useful and trouble-free.


这减少了网络中的 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 .
this Apple Developer Forum thread 中,Apple 官方代表提供了更多背景信息。 .

关于swift - 如何从 NWEndpoint.service 枚举案例解析地址和端口信息(如果可能),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60579798/

相关文章:

ios - 当类不提供实现时,为什么可以调用 init 的无参数版本?

ios - 无法在 Objective C 类中使用 Swift 协议(protocol),因为它会导致段错误 : 11

ios - Firebase Swift 的可扩展性 : Query vs Duplicate data

objective-c - NSNetService 委托(delegate)未被调用

java - 与 Bonjour 沟通的最佳方式是什么?

ios - Swift - 创建一个 UITableViewController,顶部有一个静态单元格,其余为动态单元格?

python - Pyinstaller 可执行文件在隐藏时不会运行进程

macos - Mac的Visual Studio缺少工具箱项

macos - 在OSX上使用nmake?

cocoa - cocoa 中的客户端到客户端消息传递?