如何在iOS中快速获取由AVAHI发布的服务的IP和PORT?

问题描述:

我正在使用NSNetServiceBrowser并能够在“didFindService”中找到由AVAHI发布的服务列表,如下所示: 服务出现:本地。 _https._tcp。 TEMP-Mobileyes5-1C497B9ED382 -1 服务出现:本地。 _https._tcp。 TEMP-Mobileyes5-1C497B8E3916 -1 服务出现:本地。 _https._tcp。 TEMP-Mobileyes5-1C497B9ED380 -1如何在iOS中快速获取由AVAHI发布的服务的IP和PORT?

但无法找到IP地址和相同的服务的端口号。我发现,代码是没有达到在“netServiceDidResolveAddress”我的代码是:

class ServiceDiscovery : NSObject, NSNetServiceBrowserDelegate,NSNetServiceDelegate { 

    var _browser:NSNetServiceBrowser! 
    var _service: NSNetService! 
    var services = [NSNetService]() 
    override init() { 
     _browser = NSNetServiceBrowser() 
     super.init() 
     _browser.delegate = self 
     _browser.includesPeerToPeer = true 
     _browser.searchForServicesOfType("_https._tcp.", inDomain: "local.") 
     _browser.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) 

    } 


    func netServiceBrowser(browser: NSNetServiceBrowser, didFindDomain domainString: String, moreComing: Bool) { 
     print(domainString) 
    } 

    func netServiceBrowser(aNetServiceBrowser: NSNetServiceBrowser, didFindService aNetService: NSNetService, moreComing: Bool) { 
     print("Service appeared: \(aNetService)") 
     services.append(aNetService) 
     aNetService.delegate = self 
     aNetService.resolveWithTimeout(5.0) 
    } 


    func netServiceBrowser(browser: NSNetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) { 
     print(errorDict) 
    } 

    func netServiceBrowser(browser: NSNetServiceBrowser, didRemoveService service: NSNetService, moreComing: Bool) { 
     print("Service removed: \(service)") 

    } 

    func netService(sender: NSNetService, didNotResolve errorDict: [String : NSNumber]) { 
     print(errorDict) 
    } 

    func netServiceDidResolveAddress(sender: NSNetService) { 
     print(sender.addresses![0]) 
    } 


} 

可能的原因您的问题可能是您所呼叫的

aNetService.resolveWithTimeout(5.0) 

另一个函数内部,使其尽快作为

didFindService 

结束,局部变量aNetService被销毁(因为它是didFindService福局部变量nction)

SOLUTION

我看到你已经在一个名为“_Service” 因此类范围广顶部定义变量,可以使用通过使用

_service = aNetService 
_service.resolveWithTimeout(5.0) 

你的didFindService 这应该可以解决你的问题。而且,netServiceDidResolveAddress现在应该被调用。

+0

谢谢你的很好的解决方案Aishwary,但不幸的是我没有用您的解决方案得到正确的地址,所以我没有在我的代码一些变化,现在它的工作。 –

+0

仍然存在的问题是didFind方法在iPhone中每次都不会被调用,但在iPad和模拟器中每次都会调用它。我不知道为什么 –

+0

'func netServiceBrowser(_浏览器:NetServiceBrowser,didRemove服务:NetService,moreComing:布尔){ print(“didRemoveService”)如果让ix = self.services.index(of:service) (在ix) 打印 –

import Foundation 
class ServiceDiscovery : NSObject, NetServiceBrowserDelegate,NetServiceDelegate { 

    var _browser:NetServiceBrowser! 
    var _service: NetService! 
    var services = [NetService]() 


    func searchServices(){ 
     self.services.removeAll() 
     _browser = NetServiceBrowser() 
     _browser.delegate = self 
     _browser.includesPeerToPeer = true 
     _browser.searchForServices(ofType: "_https._tcp.", inDomain: "local.") 
     _browser.schedule(in: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode) 
    } 


    func updateInterface() { 
     for service in self.services { 
      if service.port == -1 { 
       print("service \(service.name) of type \(service.type)" + 
        " not yet resolved") 
       service.delegate = self 
       service.resolve(withTimeout: 0.0) 
      } else { 

       let deviceLanController = DeviceLanController() 
       let dict = NetService.dictionary(fromTXTRecord: service.txtRecordData()!) 
       let id = self.copyStringFromTXTDict(dict as [AnyHashable: Any]?, which: "id") 
       var ipAdd = "" 
       if let address = service.addresses{ 
       if let addressOfFirstDevice = address.first{ 
        let theAddress = addressOfFirstDevice as Data 
        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST)) 
        if getnameinfo((theAddress as NSData).bytes.bindMemory(to: sockaddr.self, capacity: theAddress.count), socklen_t(theAddress.count), 
            &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 { 
         if let numAddress = String(validatingUTF8: hostname) { 
          ipAdd = numAddress 
         } 
        } 

        if let serviceId = id{ 
         deviceLanController.setDeviceAvailable(serviceId, host: ipAdd, port: "\(service.port)") 
        } 
       } 
       } 
      } 
     } 
    } 


    fileprivate func copyStringFromTXTDict(_ dict: [AnyHashable: Any]?, which: String) -> String? { 
     // Helper for getting information from the TXT data 
     var resultString: String? = nil 
     if let data = dict?[which as NSObject] as! Data? { 
      resultString = String(data: data, encoding: String.Encoding.utf8)! 

     } 
     return resultString 
    } 



    func netServiceBrowser(_ browser: NetServiceBrowser, didFindDomain domainString: String, moreComing: Bool) { 
     print("didFindDomain") 
     print(domainString) 
    } 

    func netServiceBrowser(_ aNetServiceBrowser: NetServiceBrowser, didFind aNetService: NetService, moreComing: Bool) { 
     print("didFindService") 
     self.services.append(aNetService) 
     if !moreComing { 
      aNetService.stop() 
      self.updateInterface() 
     } 
    } 

    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool){ 
     print("didRemoveService") 
     if let ix = self.services.index(of: service) { 
      self.services.remove(at: ix) 
      print("removing a service") 
      if !moreComing { 
       self.updateInterface() 
      } 
     } 
    } 

    func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) { 
     print("didNotSearch") 
     print(errorDict) 
    } 



    func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) { 
     print("didNotResolve",sender) 
     print(errorDict) 

    } 

    func netServiceWillResolve(_ sender: NetService) { 
     print("netServiceWillResolve",sender) 
    } 
    func netServiceDidResolveAddress(_ sender: NetService) { 
     print("netServiceDidResolveAddress",sender) 
     self.updateInterface() 
    } 

} 

此答案解决了我的问题。我正在解决并保存我的coredata中的每个地址,以便我可以使用该地址连接本地服务。