Как получить IP и PORT сервиса, опубликованного AVAHI в iOS swift?
Я использую NSNetServiceBrowser и могу найти список сервисов, опубликованный AVAHI в "didFindService", который выглядит так: Сервис появился: локальный. _https._tcp. TEMP-Mobileyes5-1C497B9ED382 -1 Сервис появился: локальный. _https._tcp. TEMP-Mobileyes5-1C497B8E3916 -1 Сервис появился: локальный. _https._tcp. ТЕМП-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])
}
}
2 ответа
Возможной причиной вашей проблемы может быть то, что вы звоните
aNetService.resolveWithTimeout(5.0)
внутри другой функции, так как только
didFindService
По окончании локальная переменная aNetService уничтожается (так как это локальная переменная для функции didFindService)
РЕШЕНИЕ
Я вижу, что вы уже определили переменную вверху с областью действия класса "_service". Следовательно, используйте это, используя
_service = aNetService
_service.resolveWithTimeout(5.0)
внутри вашего didFindService это должно решить вашу проблему. И, netServiceDidResolveAddress должен быть вызван сейчас.
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, чтобы я мог использовать этот адрес для подключения локальных сервисов.