iOS获取设备IP地址

  • Objective-C
/// MARK - WXIPConfig.h
#import 

static const NSString * _Nonnull kWXConfigInterfaceWifi = @"en0";
static const NSString * _Nonnull kWXConfigInterfaceCellular = @"pdp_ip0";
static const NSString * _Nonnull kWXConfigInterfaceVPN = @"utun0";
static const NSString * _Nonnull kWXIPConfigIPV4 = @"ipv4";
static const NSString * _Nonnull kWXIPConfigIPV6 = @"ipv6";

typedef NSDictionary WXConfigIPMap;

NS_ASSUME_NONNULL_BEGIN

@interface WXIPConfig : NSObject

+ (NSString *)keyWithName: (NSString*)name version: (NSString*)version;
+ (nonnull WXConfigIPMap*)getAllIPs;
+ (nullable NSString*)getIPWithInterface: (NSString*)interface version: (NSString*)version;

@end

NS_ASSUME_NONNULL_END

// MARK - WXIPConfig.m
#import "WXIPConfig.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


@implementation WXIPConfig

+ (NSString *)keyWithName: (NSString*)name version: (NSString*)version {
    return [NSString stringWithFormat:@"%@/%@", name, version];
}

+ (nonnull NSDictionary *)getAllIPs {
    NSMutableDictionary *ips = [[NSMutableDictionary alloc] initWithCapacity:32];
    struct ifaddrs *interfaces;
    if (!getifaddrs(&interfaces)) {
        struct ifaddrs *temp_interface;
        for (temp_interface = interfaces; temp_interface != NULL; temp_interface = temp_interface->ifa_next) {
            const struct sockaddr_in *addr = (const struct sockaddr_in*)temp_interface->ifa_addr;
            if (addr == NULL) {
                continue;
            }
            
            sa_family_t family = addr->sin_family;
            if (!(family == AF_INET || family == AF_INET6)) {
                continue;
            }
            
            NSString *name = [NSString stringWithUTF8String:temp_interface->ifa_name];
            const NSString *version;
            char addrBuffer[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
            const char *result;
            
            if (family == AF_INET) {
                version = kWXIPConfigIPV4;
                result = inet_ntop(AF_INET, &addr->sin_addr, addrBuffer, INET_ADDRSTRLEN);
            } else {
                version = kWXIPConfigIPV6;
                const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)temp_interface->ifa_addr;
                result = inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuffer, INET6_ADDRSTRLEN);
            }
            
            if (result != NULL) {
                NSString *key = [NSString stringWithFormat:@"%@/%@", name, version];
                ips[key] = [NSString stringWithUTF8String:addrBuffer];
            }
        }
    }
    return ips;
}

+ (nullable NSString*)getIPWithInterface: (NSString*)interface version: (NSString*)version {
    NSString *key = [WXIPConfig keyWithName:interface version:version];
    return [WXIPConfig getAllIPs][key];
}

@end

  • Swift
// Key = 接口名称+IP版本
public enum IPMapKey: RawRepresentable, Hashable, Equatable {
    case ipv4(String)
    case ipv6(String)
    
    public typealias RawValue = String
    public var rawValue: String {
        switch self {
        case .ipv4(let if_name):
            return "\(if_name)/ipv4"
        case .ipv6(let if_name):
            return "\(if_name)/ipv6"
        }
    }
    
    public init?(rawValue: String) {
        return nil
    }
    
    init?(sa_family: Int32, ifa_name: String?) {
        guard let name = ifa_name else { return nil }
        switch sa_family {
        case AF_INET:
            self = .ipv4(name)
        case AF_INET6:
            self = .ipv6(name)
        default:
            return nil
        }
    }
}

extension IPMapKey: CustomStringConvertible {
    public var description: String {
        return rawValue
    }
}

public enum IPValue {
    case ipv4(String)
    case ipv6(String)
    
    init?(sa_family: Int32, ifa_addr: String?) {
        guard let addr = ifa_addr else { return nil }
        switch sa_family {
        case AF_INET:
            self = .ipv4(addr)
        case AF_INET6:
            self = .ipv6(addr)
        default:
            return nil
        }
    }
}

extension IPValue: CustomStringConvertible {
    public var description: String {
        switch self {
        case .ipv4(let ip):
            return ip
        case .ipv6(let ip):
            return ip
        }
    }
}

public typealias IPMap = [IPMapKey: IPValue]

public class IPConfig {
    public static let Wifi = "en0"
    public static let Cellular = "pdp_ip0"
    public static let VPN = "utun0"
    /// 获取所有IP地址
    public class func getAllIPs() -> IPMap {
        var ips: IPMap = [:]
        var interfaces: UnsafeMutablePointer? = nil
        defer {
            if interfaces != nil {
                free(interfaces)
            }
        }
        
        guard getifaddrs(&interfaces) == 0 else { return ips }
        var temp_interface: UnsafeMutablePointer? = interfaces
        while let interface = temp_interface {
            if let ifa_addr = interface.pointee.ifa_addr?.pointee {
                let sa_family = Int32(ifa_addr.sa_family)
                let ifa_name = String(cString: interface.pointee.ifa_name, encoding: .utf8)
                if let key = IPMapKey(sa_family: sa_family, ifa_name: ifa_name) {
                    let len_t = max(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)
                    var inaddr = unsafeBitCast(ifa_addr, to: sockaddr_in.self).sin_addr
                    var buffer = [CChar](repeating: 0, count: Int(len_t))
                    inet_ntop(sa_family, UnsafeRawPointer(&inaddr), &buffer, UInt32(len_t))
                    let addr = String(cString: buffer, encoding: .utf8)
                    ips[key] = IPValue(sa_family: sa_family, ifa_addr: addr)
                }
            }
            temp_interface = interface.pointee.ifa_next
        }
        return ips
    }
    
    public class func getIPWithKey(_ key: IPMapKey) -> IPValue? {
        return getAllIPs()[key]
    }
}

附上Demo地址

你可能感兴趣的:(iOS获取设备IP地址)