首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bonjour:按名称搜索服务

Bonjour:按名称搜索服务
EN

Stack Overflow用户
提问于 2017-09-01 12:03:09
回答 1查看 2.5K关注 0票数 0

我有一个应用程序,需要搜索和解决一个Bonjour广告服务,其名称是事先知道。我发现的大多数与服务发现相关的Bonjour示例或多或少都是这样构造的:

  1. 调用browse以检测给定类型的所有服务(例如,这可能是_http._tcp)
  2. 对于找到的每个服务,都调用serviceFound。服务名称在这里报告。
  3. 在找到的每个服务上调用resolve
  4. 对于每个解析的服务,调用serviceResolved

Bonjour是否有可能跳过“发现”阶段,因为我提前知道了我想解决的服务的名称?我能否检测和解析一个具有已知名称的服务?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-04 07:22:43

1-应答

是的,如果你已经知道服务的名称,你可以从第三步开始。这是因为此步骤是通过DNS查找SRV记录来执行的,该记录的名称为发送到著名多播地址的服务。因此,进行此调用不需要先前的信息,而且mDNS响应程序必须是无状态的,因为底层的DNS协议是无状态的(每个响应绑定到一个唯一的请求--多个请求之间没有维护状态)。

2-示例

下面是我刚刚用Swift编写的一个示例,它通过了运行在我的iPad上的测试,以找到运行在我的Mini上的服务。因此,我们假设域是local,服务类型是_http._tcp,服务的名称是myservice,运行在主机Mac-min-deAlexandre.local上,并监听TCP端口8080。

为了跟踪有关服务的信息,例如它的主机名和TCP端口,我们定义了一个实现NetServiceDelegate协议的类:

代码语言:javascript
复制
class MyNetServiceDelegate : NSObject, NetServiceDelegate {
     public func netServiceDidResolveAddress(_ sender: NetService) {
        print(sender.hostName!, sender.port)
    }
}

这个新类将用于实例化NetService实例的委托。

因此,我们创建了一个与我们已经知道的服务相对应的NetService实例,该实例长期存储,具有某个主类的静态常量属性:

代码语言:javascript
复制
static let ns = NetService(domain: "local.", type: "_http._tcp.", name: "myservice")

它是长期储存的,因为在我们找到我们的服务之前,它不能被取消分配。

注意,类unowned(unsafe).中的委托属性声明为NetService。因此,我们还需要创建对委托实例的引用:

代码语言:javascript
复制
static let ns_deleg = MyNetServiceDelegate()

当我们想解析服务时,我们可以写:

代码语言:javascript
复制
ns.delegate = ns_deleg
ns.resolve(withTimeout: TimeInterval(10))

如果找到服务,稍后将调用委托实例(resolve()是一个非阻塞方法),在本例中,它将打印主机名和端口。

下面是我在Xcode输出窗口中得到的输出:

代码语言:javascript
复制
Mac-mini-de-Alexandre.local. 8080

最后,请注意,由于未拥有引用,编写以下代码(委托实例不久将被取消分配)将是错误的:

代码语言:javascript
复制
// bad code -- do not write that -- only here to show a common mistake
ns.delegate = MyNetServiceDelegate()
ns.resolve(withTimeout: TimeInterval(10))

3-帮助调试的技巧

下面是调试这样一个mDNS解析的一个小技巧:在Unix (例如macOS)上,只需运行以下一行:

代码语言:javascript
复制
dig -p 5353 @224.0.0.251 myservice._http._tcp.local. SRV +short

如果一个名为myservice的http服务正在运行,您将得到主机名和端口。通过我的示例,您将得到以下内容:

代码语言:javascript
复制
0 0 8080 Mac-mini-de-Alexandre.local.

因此,在尝试使用我在这里编写的Swift代码之前,只需检查使用这个shell命令是否正确地宣布了您的服务。

最后,请注意,这个基于dig的命令在每个IPv4网络接口上只进行一次mDNS查询,但是使用Apple自动完成两组mDNS请求:一组在支持IPv4的网络接口上使用IPv4到多播目标224.0.251,另一组在支持IPv6的接口上使用IPv6到多播目的地ff02::fb。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45999930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档