我有一个应用程序,需要搜索和解决一个Bonjour广告服务,其名称是事先知道。我发现的大多数与服务发现相关的Bonjour示例或多或少都是这样构造的:
browse以检测给定类型的所有服务(例如,这可能是_http._tcp)serviceFound。服务名称在这里报告。resolveserviceResolvedBonjour是否有可能跳过“发现”阶段,因为我提前知道了我想解决的服务的名称?我能否检测和解析一个具有已知名称的服务?
发布于 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协议的类:
class MyNetServiceDelegate : NSObject, NetServiceDelegate {
public func netServiceDidResolveAddress(_ sender: NetService) {
print(sender.hostName!, sender.port)
}
}这个新类将用于实例化NetService实例的委托。
因此,我们创建了一个与我们已经知道的服务相对应的NetService实例,该实例长期存储,具有某个主类的静态常量属性:
static let ns = NetService(domain: "local.", type: "_http._tcp.", name: "myservice")它是长期储存的,因为在我们找到我们的服务之前,它不能被取消分配。
注意,类unowned(unsafe).中的委托属性声明为NetService。因此,我们还需要创建对委托实例的引用:
static let ns_deleg = MyNetServiceDelegate()当我们想解析服务时,我们可以写:
ns.delegate = ns_deleg
ns.resolve(withTimeout: TimeInterval(10))如果找到服务,稍后将调用委托实例(resolve()是一个非阻塞方法),在本例中,它将打印主机名和端口。
下面是我在Xcode输出窗口中得到的输出:
Mac-mini-de-Alexandre.local. 8080最后,请注意,由于未拥有引用,编写以下代码(委托实例不久将被取消分配)将是错误的:
// 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)上,只需运行以下一行:
dig -p 5353 @224.0.0.251 myservice._http._tcp.local. SRV +short如果一个名为myservice的http服务正在运行,您将得到主机名和端口。通过我的示例,您将得到以下内容:
0 0 8080 Mac-mini-de-Alexandre.local.因此,在尝试使用我在这里编写的Swift代码之前,只需检查使用这个shell命令是否正确地宣布了您的服务。
最后,请注意,这个基于dig的命令在每个IPv4网络接口上只进行一次mDNS查询,但是使用Apple自动完成两组mDNS请求:一组在支持IPv4的网络接口上使用IPv4到多播目标224.0.251,另一组在支持IPv6的接口上使用IPv6到多播目的地ff02::fb。
https://stackoverflow.com/questions/45999930
复制相似问题