如何在 iOS swift 中获取 AVAHI 发布的服务的 IP 和 PORT?
Posted
技术标签:
【中文标题】如何在 iOS swift 中获取 AVAHI 发布的服务的 IP 和 PORT?【英文标题】:How to get IP and PORT of a service published by AVAHI in iOS swift? 【发布时间】:2017-06-28 09:41:27 【问题描述】:我正在使用 NSNetServiceBrowser,并且能够在“didFindService”中找到由 AVAHI 发布的服务列表,如下所示: 服务出现:本地。 _https._tcp。 TEMP-Mobileyes5-1C497B9ED382 -1 服务出现:本地。 _https._tcp。 TEMP-Mobileyes5-1C497B8E3916 -1 服务出现:本地。 _https._tcp。 TEMP-Mobileyes5-1C497B9ED380 -1
但无法找到同一服务的 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])
【问题讨论】:
【参考方案1】:您的问题的可能原因可能是您正在调用
aNetService.resolveWithTimeout(5.0)
在另一个函数中,所以只要
didFindService
完成,局部变量 aNetService 被销毁(因为它是 didFindService 函数的局部变量)
解决方案
我看到您已经在顶部定义了一个名为 "_service" 的具有类范围的变量 因此,使用
_service = aNetService
_service.resolveWithTimeout(5.0)
在您的 didFindService 中 这应该可以解决您的问题。而且,现在应该调用 netServiceDidResolveAddress。
【讨论】:
感谢 Aishwary 提供的好解决方案,但不幸的是,我没有通过您的解决方案获得正确的地址,所以我对代码进行了一些更改,现在它可以工作了。 仍然有问题是 didFind 方法不是每次都在 iPhone 中被调用,但在 iPad 和模拟器中它每次都会被调用。我不知道为什么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()
【参考方案2】:
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 中的每个地址,以便我可以使用该地址连接本地服务。
【讨论】:
以上是关于如何在 iOS swift 中获取 AVAHI 发布的服务的 IP 和 PORT?的主要内容,如果未能解决你的问题,请参考以下文章
iOS:Swift - 如何在触摸地图上添加精确定位并获取该位置的详细地址?