如何在swift中获取本地和子网掩码的IP地址

时间:2015-04-24 10:32:50

标签: ios ip-address

我需要使用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;
}

4 个答案:

答案 0 :(得分:8)

我已将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()!)}
  }
}

答案 1 :(得分:4)

更改了代码,因此它适用于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
    }

答案 2 :(得分:2)

这是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))!}
    }
}

答案 3 :(得分:0)

    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!)