web-dev-qa-db-fra.com

Comment obtenir l'adresse IP en swift

Comment puis-je obtenir mon adresse IP locale?

J'ai essayé d'utiliser cet exemple Obj C: comment obtenir l'adresse IP de l'iphone par programme

Quand j'arrive à la fonction getifaddrs(), je ne peux pas aller plus loin. Je ne peux pas utiliser la fonction.

Y a-t-il une autre façon de faire ou est-ce que je l'aborde de la mauvaise façon?

21
Mads Gadeberg

Répondre à Is there an alternative way to getifaddrs() for getting the ip-address?

Oui, il existe un autre moyen. Vous pouvez également obtenir l'adresse IP en utilisant ioctl(). La manière la plus propre serait de le faire en C puis de l’envelopper à Swift. Alors considérez ceci:

Créez un C Source File (Xcode devrait le créer avec un .h) et n'oubliez pas d'ajouter l'en-tête dans l'en-tête de pontage de votre projet ou dans l'en-tête de parapluie si vous avez un framework cacao touch. 

Ajoutez ce qui suit dans votre déclaration de source et de méthode en .h:

#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>

int _interfaceAddressForName(char* interfaceName, struct sockaddr* interfaceAddress) {

    struct ifreq ifr;
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    ifr.ifr_addr.sa_family = AF_INET;

    strncpy(ifr.ifr_name, interfaceName, IFNAMSIZ-1);

    int ioctl_res;
    if ( (ioctl_res = ioctl(fd, SIOCGIFADDR, &ifr)) < 0){
        return ioctl_res;
    }

    close(fd);
    memcpy(interfaceAddress, &ifr.ifr_addr, sizeof(struct sockaddr));
    return 0;
}

Votre wrapper Swift pourrait ressembler à quelque chose comme:

public enum Error:ErrorType {
    case IOCTLFailed(Int32)
    case StringIsNotAnASCIIString
}

public func interfaceAddress(forInterfaceWithName interfaceName: String) throws -> sockaddr_in {

    guard let cString = interfaceName.cStringUsingEncoding(NSASCIIStringEncoding) else {
        throw Error.StringIsNotAnASCIIString
    }

    let addressPtr = UnsafeMutablePointer<sockaddr>.alloc(1)
    let ioctl_res = _interfaceAddressForName(strdup(cString), addressPtr)
    let address = addressPtr.move()
    addressPtr.dealloc(1)

    if ioctl_res < 0 {
        throw Error.IOCTLFailed(errno)
    } else {
        return unsafeBitCast(address, sockaddr_in.self)
    }
}

Ensuite, vous pouvez l'utiliser dans votre code comme:

let interfaceName = "en0"
do {
    let wlanInterfaceAddress = try interfaceAddress(forInterfaceWithName: interfaceName)
    print(String.fromCString(inet_ntoa(wlanInterfaceAddress.sin_addr))!)
} catch {
    if case Error.IOCTLFailed(let errno) = error where errno == ENXIO {
        print("interface(\(interfaceName)) is not available")
    } else {
        print(error)
    }
}

en0 est généralement l'interface dont vous avez besoin, ce qui signifie WLAN

Si vous devez également connaître les noms d’interface disponibles, vous pouvez utiliser if_indextoname():

public func interfaceNames() -> [String] {

    let MAX_INTERFACES = 128;

    var interfaceNames = [String]()
    let interfaceNamePtr = UnsafeMutablePointer<Int8>.alloc(Int(IF_NAMESIZE))
    for interfaceIndex in 1...MAX_INTERFACES {
        if (if_indextoname(UInt32(interfaceIndex), interfaceNamePtr) != nil){
            if let interfaceName = String.fromCString(interfaceNamePtr) {
                interfaceNames.append(interfaceName)
            }
        } else {
            break
        }
    }

    interfaceNamePtr.dealloc(Int(IF_NAMESIZE))
    return interfaceNames
}
2
ambientlight
   func getIfConfigOutput() -> [String:String] {
    let cmd = "for i in $(ifconfig -lu); do if ifconfig $i | grep -q \"status: active\" ; then echo $i; fi; done"
    let interfaceString = Shell(cmd)
    let interfaceArray = interfaceString.components(separatedBy: "\n")
    var finalDictionary:[String:String] = [String:String]()
    for (i,_) in interfaceArray.enumerated() {
        if (interfaceArray[i].hasPrefix("en")){
            let sp = Shell("ifconfig \(interfaceArray[i]) | grep \"inet \" | grep -v 127.0.0.1 | cut -d\\  -f2")
          finalDictionary[interfaceArray[i]] = sp.replacingOccurrences(of: "\n", with: "")
        }
    }
  print(finalDictionary)
    return finalDictionary
}
func Shell(_ args: String) -> String {
    var outstr = ""
    let task = Process()
    task.launchPath = "/bin/sh"
    task.arguments = ["-c", args]
    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    if let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
        outstr = output as String
    }
    task.waitUntilExit()
    return outstr
}

Cela vous aidera. Code Retourne un dictionnaire avec des interfaces et des adresses IP associées.

1
sudarshan Mane