【问题标题】:How to get local and subnet mask ip address in swift如何在swift中获取本地和子网掩码IP地址
【发布时间】:2015-07-02 22:07:16
【问题描述】:

我需要使用 Swift 代码获取本地 IP 地址和子网掩码。

请帮助我。我有一些在 Objective-C 中工作的代码。如何在 Swift 中获取等效代码?

下面我添加了Objective-C代码:

+(NSDictionary *)getLocalIPAddress{ 
NSDictionary *dictIPDetails; 
NSString *address = @"error";
NSString *netmask = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;int success = 0;

    // retrieve the current interfaces - returns 0 on success
    success = getifaddrs(&interfaces);

    if (success == 0)
    {
        temp_addr = interfaces;

        while(temp_addr != NULL)
        {
            // check if interface is en0 which is the wifi connection on the iPhone
            if(temp_addr->ifa_addr->sa_family == AF_INET)
            {
                if([@(temp_addr->ifa_name) isEqualToString:@"en0"])
                {
                    address = @(inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
                    netmask = @(inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr));
                    dictIPDetails = @{LOCAL_IP_ADDR:address,SUBNET_MASK:netmask};
                }
            }

            temp_addr = temp_addr->ifa_next;
        }
    }

    freeifaddrs(interfaces);

    return dictIPDetails;
}

【问题讨论】:

    标签: ios ip-address


    【解决方案1】:

    我已经修改了here 的答案,将网络掩码和 ip 一起包含在内。

    使用下面的代码,您可以执行以下操作:

      let ip = getIFAddresses().last!.ip
      let netmask = getIFAddresses().last!.netmask
    

    希望这会有所帮助。

      struct NetInfo {
        let ip: String
        let netmask: String
      }
    
      // Get the local ip addresses used by this node
      func getIFAddresses() -> [NetInfo] {
        var addresses = [NetInfo]()
    
        // Get list of all interfaces on the local machine:
        var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
        if getifaddrs(&ifaddr) == 0 {
    
          // 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
    
            // 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) {
    
                // Convert interface address to a human readable string:
                var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                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) {
    
                      var net = ptr.memory.ifa_netmask.memory
                      var netmaskName = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                      getnameinfo(&net, socklen_t(net.sa_len), &netmaskName, socklen_t(netmaskName.count),
                        nil, socklen_t(0), NI_NUMERICHOST) == 0
                      if let netmask = String.fromCString(netmaskName) {
                        addresses.append(NetInfo(ip: address, netmask: netmask))
                      }
                    }
                }
              }
            }
          }
          freeifaddrs(ifaddr)
        }
        return addresses
      }
    

    如果您需要更多花里胡哨,我有这个版本的NetInfo,它也会计算您的网络和广播地址。

    struct NetInfo {
      // IP Address
      let ip: String
    
      // Netmask Address
      let netmask: String
    
      // CIDR: Classless Inter-Domain Routing
      var cidr: Int {
        var cidr = 0
        for number in binaryRepresentation(netmask) {
          let numberOfOnes = number.componentsSeparatedByString("1").count - 1
          cidr += numberOfOnes
        }
        return cidr
      }
    
      // Network Address
      var network: String {
        return bitwise(&, net1: ip, net2: netmask)
      }
    
      // Broadcast Address
      var broadcast: String {
        let inverted_netmask = bitwise(~, net1: netmask)
        let broadcast = bitwise(|, net1: network, net2: inverted_netmask)
        return broadcast
      }
    
      private func binaryRepresentation(s: String) -> [String] {
        var result: [String] = []
        for numbers in (split(s) {$0 == "."}) {
          if let intNumber = numbers.toInt() {
            if let binary = String(intNumber, radix: 2).toInt() {
              result.append(NSString(format: "%08d", binary) as String)
            }
          }
        }
        return result
      }
    
      private func bitwise(op: (UInt8,UInt8) -> UInt8, net1: String, net2: String) -> String {
        let net1numbers = toInts(net1)
        let net2numbers = toInts(net2)
        var result = ""
        for i in 0..<net1numbers.count {
          result += "\(op(net1numbers[i],net2numbers[i]))"
          if i < (net1numbers.count-1) {
            result += "."
          }
        }
        return result
      }
    
      private func bitwise(op: UInt8 -> UInt8, net1: String) -> String {
        let net1numbers = toInts(net1)
        var result = ""
        for i in 0..<net1numbers.count {
          result += "\(op(net1numbers[i]))"
          if i < (net1numbers.count-1) {
            result += "."
          }
        }
        return result
      }
    
      private func toInts(networkString: String) -> [UInt8] {
        return (split(networkString){$0 == "."}).map{UInt8($0.toInt()!)}
      }
    }
    

    【讨论】:

    • 函数toInts上的ipv6地址的代码由于map函数中的强制解包而崩溃
    【解决方案2】:

    更改了代码,使其适用于 swift 3:

     
        struct NetInfo {
            let ip: String
            let netmask: String
        }
        
        // Get the local ip addresses used by this node
        class func getIFAddresses() -> [NetInfo] {
            var addresses = [NetInfo]()
            
            // Get list of all interfaces on the local machine:
            var ifaddr : UnsafeMutablePointer<ifaddrs>? = nil
            if getifaddrs(&ifaddr) == 0 {
                
                    var ptr = ifaddr;
                    while ptr != nil {
                    
                    let flags = Int32((ptr?.pointee.ifa_flags)!)
                    var addr = ptr?.pointee.ifa_addr.pointee
                    
                    // 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) {
                            
                            // Convert interface address to a human readable string:
                            var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                            if (getnameinfo(&addr!, socklen_t((addr?.sa_len)!), &hostname, socklen_t(hostname.count),
                                            nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                                if let address = String.init(validatingUTF8:hostname) {
                                    
                                    var net = ptr?.pointee.ifa_netmask.pointee
                                    var netmaskName = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                                    getnameinfo(&net!, socklen_t((net?.sa_len)!), &netmaskName, socklen_t(netmaskName.count),
                                                nil, socklen_t(0), NI_NUMERICHOST)// == 0
                                    if let netmask = String.init(validatingUTF8:netmaskName) {
                                        addresses.append(NetInfo(ip: address, netmask: netmask))
                                    }
                                }
                            }
                        }
                    }
                    ptr = ptr?.pointee.ifa_next
                    }
                freeifaddrs(ifaddr)
            }
            return addresses
        }

    【讨论】:

    • 感谢您更新 Swift 3 的代码。由于我是网络编程概念和 Swift 3 的新手,您能否提供示例应用程序?我想获取本地 IP、子网以及想计算网络和广播地址。
    【解决方案3】:

    这是 Mellson 为 Swift 2 重新编写的扩展 NetInfo(希望它可以节省其他人的时间)

    struct NetInfo {
        // IP Address
        let ip: String
    
        // Netmask Address
        let netmask: String
    
        // CIDR: Classless Inter-Domain Routing
        var cidr: Int {
            var cidr = 0
            for number in binaryRepresentation(netmask) {
                let numberOfOnes = number.componentsSeparatedByString("1").count - 1
                cidr += numberOfOnes
            }
            return cidr
        }
    
        // Network Address
        var network: String {
            return bitwise(&, net1: ip, net2: netmask)
        }
    
        // Broadcast Address
        var broadcast: String {
            let inverted_netmask = bitwise(~, net1: netmask)
            let broadcast = bitwise(|, net1: network, net2: inverted_netmask)
            return broadcast
        }
    
    
        private func binaryRepresentation(s: String) -> [String] {
            var result: [String] = []
            for numbers in (s.characters.split {$0 == "."}) {
                if let intNumber = Int(String(numbers)) {
                    if let binary = Int(String(intNumber, radix: 2)) {
                        result.append(NSString(format: "%08d", binary) as String)
                    }
                }
            }
            return result
        }
    
        private func bitwise(op: (UInt8,UInt8) -> UInt8, net1: String, net2: String) -> String {
            let net1numbers = toInts(net1)
            let net2numbers = toInts(net2)
            var result = ""
            for i in 0..<net1numbers.count {
                result += "\(op(net1numbers[i],net2numbers[i]))"
                if i < (net1numbers.count-1) {
                    result += "."
                }
            }
            return result
        }
    
        private func bitwise(op: UInt8 -> UInt8, net1: String) -> String {
            let net1numbers = toInts(net1)
            var result = ""
            for i in 0..<net1numbers.count {
                result += "\(op(net1numbers[i]))"
                if i < (net1numbers.count-1) {
                    result += "."
                }
            }
            return result
        }
    
        private func toInts(networkString: String) -> [UInt8] {
            return (networkString.characters.split {$0 == "."}).map{UInt8(String($0))!}
        }
    }
    

    【讨论】:

      【解决方案4】:
          let theOutput = Pipe()
      
      func shell(Path:String ,args: String...) -> Int32 {
          let task = Process()
          task.launchPath = Path
          task.arguments = args
          task.standardOutput = theOutput
          task.standardError = theOutput
      
          task.launch()
          task.waitUntilExit()
      
          return task.terminationStatus
      }
      shell(Path:"/usr/sbin/arp",args: "-a")
      
      let theTaskData = theOutput.fileHandleForReading.readDataToEndOfFile()
      let stringResult = String(data: theTaskData, encoding: .utf8)
      
      print(stringResult!)
      

      【讨论】:

      • 我希望这对你有帮助,这可以打印你子网的所有 ip 和 Mac,我使用 xcode 8.1 & swift 3
      猜你喜欢
      • 1970-01-01
      • 2014-12-31
      • 1970-01-01
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 2015-10-18
      • 2015-05-16
      相关资源
      最近更新 更多