简体   繁体   中英

How to get local and subnet mask ip address in swift

I need to get the local IP address and subnet mask using Swift code.

Please help me in this. I have some code working in Objective-C. How to get the equivalent code in Swift??

Below I have added Objective-C code:

+(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;
}

I have modified the answer from here to include netmask along with ip.

With the code below you can do something like this:

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

Hope this helps.

  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
  }

If you need more bells and whistles I have this version of NetInfo which will calculate your network and broadcast addresses as well.

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

changed the code so it works with 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 } 

Here's Mellson's extended NetInfo re-written for Swift 2 (Hope it save's someone else the time to work it out)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM