2015-11-30 27 views
3

我有以下代碼,它可以成功檢索連接到我的路由器的所有IP。但我需要爲每個IP獲取MAC地址。管理ifaddrs以及在Swift中返回MAC地址

地址所以不是返回與[ips]陣列,被返回作爲字典[ips:0000000, mac: 000000]

是否有可能與更改爲以下代碼(來自How to get Ip address in swift)實現?

func getIFAddresses() -> [String] { 


print("GET IF ADDRESSSE") 

var addresses = [String]() 

// Get list of all interfaces on the local machine: 
var ifaddr : UnsafeMutablePointer<ifaddrs> = nil 
if getifaddrs(&ifaddr) == 0 { 

    print("getifaddrs\(getifaddrs)") 

    // For each interface ... 
    for (var ptr = ifaddr; ptr != nil; ptr = ptr.memory.ifa_next) { 
     let flags = Int32(ptr.memory.ifa_flags) 
     var addr = ptr.memory.ifa_addr.memory 

     print("flags\(flags)") 
     print("addr\(addr)") 

     // Check for running IPv4, IPv6 interfaces. Skip the loopback interface. 
     if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) { 



      if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) { 

       print("addr.sa_family\(addr.sa_family)") 

       // Convert interface address to a human readable string: 
       var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0) 

       print("hostname\(hostname)") 

       if (getnameinfo(
        &addr, socklen_t(addr.sa_len), 
        &hostname, 
        socklen_t(hostname.count), 
        nil, 
        socklen_t(0), NI_NUMERICHOST) == 0) { 


         if let address = String.fromCString(hostname) { 
          addresses.append(address) 
         } 
       } 
      } 
     } 
    } 
    freeifaddrs(ifaddr) 
    print("freeifaddrs\(freeifaddrs)") 
} 
print("ADDRESSES \(addresses)") 
return addresses 

}

+0

你試過嗎?代碼是否工作?如果不是什麼問題? – zaph

+0

@DanBeaulieu你是正確的,我正在刪除評論。我應該知道,比試圖解釋爲什麼通常不推薦反對選票更好。是的,我已將我的答案複製並用作另一個問題的答案。 – zaph

回答

7

備註/澄清:這是一個問題的答案「管理ifaddrs返回MAC斯威夫特地址以及」「是否有可能修改代碼從How to get Ip address in swift返回MAC地址,以及」 這不是解決‘檢索所有連接到我的路由器’ 這也是在這個問題身體中提到的IP地址。)

下面是參考代碼的擴展,它返回 本地(啓動和運行)接口作爲 的(接口名稱,IP地址,MAC地址)元組的陣列。 MAC地址從類型AF_LINK 的接口中檢索,這些接口在接口列表中存儲爲sockaddr_dl結構。 這是一個可變長度的結構,而Swift的嚴格類型系統使得一些指針玩雜耍是必要的。

重要提示:此代碼旨在運行在Mac電腦上。 無法獲取iOS設備上的MAC地址。 的iOS 故意返回 「02:00:00:00:00:00」 作爲隱私的原因所有接口的硬件地址 ,例如參見 Trouble with MAC address in iOS 7.0.2

func getInterfaces() -> [(name : String, addr: String, mac : String)] { 

    var addresses = [(name : String, addr: String, mac : String)]() 
    var nameToMac = [ String : String ]() 

    // Get list of all interfaces on the local machine: 
    var ifaddr : UnsafeMutablePointer<ifaddrs> = nil 
    if getifaddrs(&ifaddr) == 0 { 

     // For each interface ... 
     var ptr = ifaddr 
     while ptr != nil { 
      defer { ptr = ptr.memory.ifa_next } 

      let flags = Int32(ptr.memory.ifa_flags) 
      let addr = ptr.memory.ifa_addr 

      if let name = String.fromCString(ptr.memory.ifa_name) { 

       // Check for running IPv4, IPv6 interfaces. Skip the loopback interface. 
       if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) { 

        if addr.memory.sa_family == UInt8(AF_LINK) { 
         // Get MAC address from sockaddr_dl structure and store in nameToMac dictionary: 
         let dl = UnsafePointer<sockaddr_dl>(ptr.memory.ifa_addr) 
         let lladdr = UnsafeBufferPointer(start: UnsafePointer<Int8>(dl) + 8 + Int(dl.memory.sdl_nlen), 
                 count: Int(dl.memory.sdl_alen)) 
         if lladdr.count == 6 { 
          nameToMac[name] = lladdr.map { String(format:"%02hhx", $0)}.joinWithSeparator(":") 
         } 
        } 

        if addr.memory.sa_family == UInt8(AF_INET) || addr.memory.sa_family == UInt8(AF_INET6) { 
         // Convert interface address to a human readable string: 
         var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0) 
         if (getnameinfo(addr, socklen_t(addr.memory.sa_len), &hostname, socklen_t(hostname.count), 
          nil, socklen_t(0), NI_NUMERICHOST) == 0) { 
          if let address = String.fromCString(hostname) { 
           addresses.append((name: name, addr: address, mac : "")) 
          } 
         } 
        } 
       } 
      } 
     } 
     freeifaddrs(ifaddr) 
    } 

    // Now add the mac address to the tuples: 
    for (i, addr) in addresses.enumerate() { 
     if let mac = nameToMac[addr.name] { 
      addresses[i] = (name: addr.name, addr: addr.addr, mac : mac) 
     } 
    } 

    return addresses 
} 

你必須添加

#include <ifaddrs.h> 
#include <net/if_dl.h> 

到橋接頭文件進行編譯。

用法示例:

for addr in getInterfaces() { 
    print(addr) 
} 
// ("en0", "fe80::1234:7fff:fe2e:8765%en0", "a9:55:6f:2e:57:78") 
// ("en0", "192.168.2.108", "a9:55:6f:2e:57:78") 
// ... 

更新斯威夫特3(Xcode中8):

func getInterfaces() -> [(name : String, addr: String, mac : String)] { 

    var addresses = [(name : String, addr: String, mac : String)]() 
    var nameToMac = [ String: String ]() 

    // Get list of all interfaces on the local machine: 
    var ifaddr : UnsafeMutablePointer<ifaddrs>? 
    guard getifaddrs(&ifaddr) == 0 else { return [] } 
    guard let firstAddr = ifaddr else { return [] } 

    // For each interface ... 
    for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) { 
     let flags = Int32(ptr.pointee.ifa_flags) 
     if let addr = ptr.pointee.ifa_addr { 
      let name = String(cString: ptr.pointee.ifa_name) 

      // Check for running IPv4, IPv6 interfaces. Skip the loopback interface. 
      if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) { 
       switch Int32(addr.pointee.sa_family) { 
       case AF_LINK: 
        // Get MAC address from sockaddr_dl structure and store in nameToMac dictionary: 
        addr.withMemoryRebound(to: sockaddr_dl.self, capacity: 1) { dl in 
         dl.withMemoryRebound(to: Int8.self, capacity: 8 + Int(dl.pointee.sdl_nlen + dl.pointee.sdl_alen)) { 
          let lladdr = UnsafeBufferPointer(start: $0 + 8 + Int(dl.pointee.sdl_nlen), 
                  count: Int(dl.pointee.sdl_alen)) 
          if lladdr.count == 6 { 
           nameToMac[name] = lladdr.map { String(format:"%02hhx", $0)}.joined(separator: ":") 
          } 
         } 
        } 
       case AF_INET, AF_INET6: 
        // Convert interface address to a human readable string: 
        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST)) 
        if (getnameinfo(addr, socklen_t(addr.pointee.sa_len), 
            &hostname, socklen_t(hostname.count), 
            nil, socklen_t(0), NI_NUMERICHOST) == 0) { 
         let address = String(cString: hostname) 
         addresses.append((name: name, addr: address, mac : "")) 
        } 
       default: 
        break 
       } 
      } 
     } 
    } 

    freeifaddrs(ifaddr) 

    // Now add the mac address to the tuples: 
    for (i, addr) in addresses.enumerated() { 
     if let mac = nameToMac[addr.name] { 
      addresses[i] = (name: addr.name, addr: addr.addr, mac : mac) 
     } 
    } 

    return addresses 
} 
+1

感謝您花費一些時間。我很感激。對不起,在使用您的代碼時不會將您的信用添加到我的問題中。 – GuiSoySauce

+0

這段代碼是打算讓所有的設備連接到wifi網絡或我的本地機器信息? – GuiSoySauce

+0

@GuiSoySauce:這是用於本地機器上的接口(對於引用的代碼也是如此http://stackoverflow.com/questions/25626117/how-to-get-ip-address-in-swift和代碼從你以前的問題http://www.chrisandtennille.com/code/IPAddress.c)。 –

0

如果你會使用這個框架裏面,你必須添加一個。帶有此配置的模型映射文件

module ifaddrs [system] [extern_c] { 
    header 
    "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/ifaddrs.h" 
    export * 
} 

module net [system] [extern_c] { 

    module types { 
     header "/usr/include/sys/types.h" 
     export * 
    } 

    module if_dl { 

     header 
     "/usr/include/net/if_dl.h" 
     export * 
    } 

} 

,然後在.swift文件

import ifaddrs 
import net.if_dl