在swift 3中试试Bonjour
这是我的代码,我可以接收委托func netServiceDidResolveAddress(_ sender: NetService) {
print("netServiceDidResolveAddress service name (sender.name) of type (sender.type)," +
"port (sender.port), addresses (sender.addresses)")
}
这是我的结果
netServiceDidResolveAddress服务名称Webber的Mac mini类型_myapp._tcp。,端口5678,addresses可选([<1002162e c0a80205 00000000 00000000>, <1c1e162e 00000000 fe800000 00000000 00bce7ad . cn)24 b4b7e8 08000000>)
c0a80205是我要找的IP => 192.168.2.5
地址是[Data], Apple说
服务地址。这是NSData实例的NSArray,其中每个都包含一个适合使用的结构体sockaddr(2)连接。在没有解析地址的情况下服务或服务尚未解析,则为空NSArray返回。
我仍然困惑为什么Data不能使用。btyes ?苹果说"这是NSData实例的NSArray "但我不能像使用NSData
那样使用它如何将地址解析为可读的IP字符串?
我以前尝试过,但没有得到结果,因为我除了…
let thedata = NSData(bytes: sender.addresses, length: (sender.addresses?.count)!)
var storage = sockaddr_storage()
thedata.getBytes(&storage, length: sizeof(sockaddr_storage))
if Int32(storage.ss_family) == AF_INET {
let addr4 = withUnsafePointer(&storage) {UnsafePointer<sockaddr_in>($0).pointee }
print(inet_ntoa(addr4.sin_addr));
}
任何建议都会有所帮助,谢谢
我在Swift 3中是这样做的。
func netServiceDidResolveAddress(_ sender: NetService) {
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
guard let data = sender.addresses?.first else { return }
data.withUnsafeBytes { (pointer:UnsafePointer<sockaddr>) -> Void in
guard getnameinfo(pointer, socklen_t(data.count), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 else {
return
}
}
let ipAddress = String(cString:hostname)
print(ipAddress)
}
迅速5
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
data.withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Void in
let sockaddrPtr = pointer.bindMemory(to: sockaddr.self)
guard let unsafePtr = sockaddrPtr.baseAddress else { return }
guard getnameinfo(unsafePtr, socklen_t(data.count), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 else {
return
}
}
let ipAddress = String(cString:hostname)
print(ipAddress)
编辑Phil Coles对Swift 5.0警告免费解决方案的回答:
func netServiceDidResolveAddress(_ sender: NetService) {
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
guard let data = sender.addresses?.first else { return }
data.withUnsafeBytes { ptr in
guard let sockaddr_ptr = ptr.baseAddress?.assumingMemoryBound(to: sockaddr.self) else {
// handle error
return
}
var sockaddr = sockaddr_ptr.pointee
guard getnameinfo(sockaddr_ptr, socklen_t(sockaddr.sa_len), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 else {
return
}
}
let ipAddress = String(cString:hostname)
print(ipAddress)
}
OK…这不是一个聪明的答案,至少我可以得到可读的IP
使用这个函数获取IP字符串
let bonjourDevices = [NetService]()
let bonjourDevice = bonjourDevices[0]
let host = self.getIPV4StringfromAddress(address:bonjourDevice.addresses!)
func getIPV4StringfromAddress(address: [Data] , port : Int ) -> String{
let data = address.first! as NSData;
var ip1 = UInt8(0)
data.getBytes(&ip1, range: NSMakeRange(4, 1))
var ip2 = UInt8(0)
data.getBytes(&ip2, range: NSMakeRange(5, 1))
var ip3 = UInt8(0)
data.getBytes(&ip3, range: NSMakeRange(6, 1))
var ip4 = UInt8(0)
data.getBytes(&ip4, range: NSMakeRange(7, 1))
let ipStr = String(format: "%d.%d.%d.%d:%d",ip1,ip2,ip3,ip4,port);
return ipStr;
}
我不能使它与Data
工作,但使用NSData
,我会使用这个:
extension NSData {
func castToCPointer<T>() -> T {
let mem = UnsafeMutablePointer<T>.allocate(capacity: MemoryLayout<T.Type>.size)
self.getBytes(mem, length: MemoryLayout<T.Type>.size)
return mem.move()
}
}
我们有netServiceDidResolveAddress
:
func netServiceDidResolveAddress(_ sender: NetService) {
if let addresses = sender.addresses, addresses.count > 0 {
for address in addresses {
let data = address as NSData
let inetAddress: sockaddr_in = data.castToCPointer()
if inetAddress.sin_family == __uint8_t(AF_INET) {
if let ip = String(cString: inet_ntoa(inetAddress.sin_addr), encoding: .ascii) {
// IPv4
print(ip)
}
} else if inetAddress.sin_family == __uint8_t(AF_INET6) {
let inetAddress6: sockaddr_in6 = data.castToCPointer()
let ipStringBuffer = UnsafeMutablePointer<Int8>.allocate(capacity: Int(INET6_ADDRSTRLEN))
var addr = inetAddress6.sin6_addr
if let ipString = inet_ntop(Int32(inetAddress6.sin6_family), &addr, ipStringBuffer, __uint32_t(INET6_ADDRSTRLEN)) {
if let ip = String(cString: ipString, encoding: .ascii) {
// IPv6
print(ip)
}
}
ipStringBuffer.deallocate(capacity: Int(INET6_ADDRSTRLEN))
}
}
}
}
我得到以下结果(在显示之前将ip存储在数组中):
["172.16.10.120", "172.16.8.251", "::", "::82c9:d9a5:2eed:1c87"]
受https://gist.github.com/agrippa1994/d8c66a2ded74fb2dd801启发的代码,在Swift 2.3中编写,并适用于Swift 3.0