关于iOS配置ipv6和ipv4地址不同时的处理办法

来源:互联网 发布:初中优化测试卷答案 编辑:程序博客网 时间:2024/06/05 17:51

当ipv6和ipv4地址不同时的处理:

-(void)getHost{if ([DeviceInfo isIpv6]) {        return hostIpv6;    }    return hostIpv4;}-(void)getBaseUrl{    if ([DeviceInfo isIpv6]) {        return baseUrlIpv6;    }    return baseUrlIpv4;}

具体的DeviceInfo类如下

DeviceInfo.h

#import <Foundation/Foundation.h>@interface DeviceInfo : NSObject+ (NSString *) OpenUDID;+ (BOOL)isIpv6;+ (NSString *)getIPAddress:(BOOL)preferIPv4;@end

DeviceInfo.m

#import "YCX_DeviceInfo.h"#import <AssetsLibrary/AssetsLibrary.h>#import <MobileCoreServices/MobileCoreServices.h>#import "SvUDIDTools.h"#include <ifaddrs.h>#include <arpa/inet.h>#include <net/if.h>#define IOS_CELLULAR    @"pdp_ip0"#define IOS_WIFI        @"en0"#define IOS_VPN         @"utun0"#define IP_ADDR_IPv4    @"ipv4"#define IP_ADDR_IPv6    @"ipv6"@implementation DeviceInfo+ (BOOL)isIpv6{    NSString *ipv6 = [self getIPAddress:NO];    NSInteger count = [ipv6 countOccurencesOfString:@":"];    if (count >= 6) {        return YES;    }    return NO;}+ (NSString *)getIPAddress:(BOOL)preferIPv4{    NSArray *searchArray = preferIPv4 ?    @[ IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :    @[ IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;    NSDictionary *addresses = [self getIPAddresses];    __block NSString *address;    [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)     {         address = addresses[key];         if(address) *stop = YES;     } ];    return address ? address : @"0.0.0.0";}+ (NSDictionary *)getIPAddresses{    NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];    // retrieve the current interfaces - returns 0 on success    struct ifaddrs *interfaces;    if(!getifaddrs(&interfaces)) {        // Loop through linked list of interfaces        struct ifaddrs *interface;        for(interface=interfaces; interface; interface=interface->ifa_next) {            if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {                continue; // deeply nested code harder to read            }            const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;            char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];            if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {                NSString *name = [NSString stringWithUTF8String:interface->ifa_name];                NSString *type;                if(addr->sin_family == AF_INET) {                    if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {                        type = IP_ADDR_IPv4;                    }                } else {                    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;                    if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {                        type = IP_ADDR_IPv6;                    }                }                if(type) {                    NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];                    addresses[key] = [NSString stringWithUTF8String:addrBuf];                }            }        }        // Free memory        freeifaddrs(interfaces);    }    return [addresses count] ? addresses : nil;}+ (NSString *) OpenUDID{    return [[UIDevice currentDevice].identifierForVendor UUIDString];}

使用到的SvUDIDTools类方法设置如下:

#import <Foundation/Foundation.h>@interface SvUDIDTools : NSObject/* * @brief obtain Unique Device Identity */+ (NSString*)UDID;@end#import "SvUDIDTools.h"#import <Security/Security.h>#include <sys/socket.h>#include <sys/sysctl.h>#include <net/if.h>#include <net/if_dl.h>// replace the identity with your company's domainstatic const char kKeychainUDIDItemIdentifier[]  = "UUID";static const char kKeyChainUDIDAccessGroup[] = "请设置你自己的";@implementation SvUDIDTools+ (NSString*)UDID{    NSString *udid = [SvUDIDTools getUDIDFromKeyChain];    if (!udid) {        NSString *sysVersion = [UIDevice currentDevice].systemVersion;        CGFloat version = [sysVersion floatValue];        if (version >= 7.0) {            udid = [SvUDIDTools _UDID_iOS7];        }        else if (version >= 2.0) {            udid = [SvUDIDTools _UDID_iOS6];        }        [SvUDIDTools settUDIDToKeyChain:udid];    }    return udid;}/* * iOS 6.0 * use wifi's mac address */+ (NSString*)_UDID_iOS6{    return [SvUDIDTools getMacAddress];}/* * iOS 7.0 * Starting from iOS 7, the system always returns the value 02:00:00:00:00:00  * when you ask for the MAC address on any device. * use identifierForVendor + keyChain * make sure UDID consistency atfer app delete and reinstall */+ (NSString*)_UDID_iOS7{    return [[UIDevice currentDevice].identifierForVendor UUIDString];}#pragma mark -#pragma mark Helper Method for Get Mac Address// from http://stackoverflow.com/questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone+ (NSString *)getMacAddress{    int                 mgmtInfoBase[6];    char                *msgBuffer = NULL;    size_t              length;    unsigned char       macAddress[6];    struct if_msghdr    *interfaceMsgStruct;    struct sockaddr_dl  *socketStruct;    NSString            *errorFlag = nil;    // Setup the management Information Base (mib)    mgmtInfoBase[0] = CTL_NET;        // Request network subsystem    mgmtInfoBase[1] = AF_ROUTE;       // Routing table info    mgmtInfoBase[2] = 0;    mgmtInfoBase[3] = AF_LINK;        // Request link layer information    mgmtInfoBase[4] = NET_RT_IFLIST;  // Request all configured interfaces    // With all configured interfaces requested, get handle index    if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)        errorFlag = @"if_nametoindex failure";    else    {        // Get the size of the data available (store in len)        if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)            errorFlag = @"sysctl mgmtInfoBase failure";        else        {            // Alloc memory based on above call            if ((msgBuffer = malloc(length)) == NULL)                errorFlag = @"buffer allocation failure";            else            {                // Get system information, store in buffer                if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)                    errorFlag = @"sysctl msgBuffer failure";            }        }    }    // Befor going any further...    if (errorFlag != NULL)    {        NSLog(@"Error: %@", errorFlag);        if (msgBuffer) {            free(msgBuffer);        }        return errorFlag;    }    // Map msgbuffer to interface message structure    interfaceMsgStruct = (struct if_msghdr *) msgBuffer;    // Map to link-level socket structure    socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);    // Copy link layer address data in socket structure to an array    memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);    // Read from char array into a string object, into traditional Mac address format    NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",                                  macAddress[0], macAddress[1], macAddress[2],                                  macAddress[3], macAddress[4], macAddress[5]];    NSLog(@"Mac Address: %@", macAddressString);    // Release the buffer memory    free(msgBuffer);    return macAddressString;}#pragma mark -#pragma mark Helper Method for make identityForVendor consistency+ (NSString*)getUDIDFromKeyChain{    NSMutableDictionary *dictForQuery = [[NSMutableDictionary alloc] init];    [dictForQuery setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];    // set Attr Description for query    [dictForQuery setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]                    forKey:(NSString *)kSecAttrDescription];    // set Attr Identity for query    NSData *keychainItemID = [NSData dataWithBytes:kKeychainUDIDItemIdentifier                                            length:strlen(kKeychainUDIDItemIdentifier)];    [dictForQuery setObject:keychainItemID forKey:(id)kSecAttrGeneric];    // The keychain access group attribute determines if this item can be shared    // amongst multiple apps whose code signing entitlements contain the same keychain access group.    NSString *accessGroup = [NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];    if (accessGroup != nil)    {#if TARGET_IPHONE_SIMULATOR        // Ignore the access group if running on the iPhone simulator.        //        // Apps that are built for the simulator aren't signed, so there's no keychain access group        // for the simulator to check. This means that all apps can see all keychain items when run        // on the simulator.        //        // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the        // simulator will return -25243 (errSecNoAccessForItem).#else        [dictForQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];#endif    }    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecMatchCaseInsensitive];    [dictForQuery setValue:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnData];    OSStatus queryErr   = noErr;    NSData   *udidValue = nil;    NSString *udid      = nil;    CFTypeRef typeRef = (__bridge CFTypeRef)udidValue;    queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery, &typeRef);    NSMutableDictionary *dict = nil;    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];    CFTypeRef typeDict = (__bridge CFTypeRef)dict;    queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery, &typeDict);    if (queryErr == errSecItemNotFound) {        NSLog(@"KeyChain Item: %@ not found!!!", [NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]);    }    else if (queryErr != errSecSuccess) {        NSLog(@"KeyChain Item query Error!!! Error code:%d", queryErr);    }    if (queryErr == errSecSuccess) {        NSLog(@"KeyChain Item: %@", udidValue);        if (udidValue) {            udid = [NSString stringWithUTF8String:udidValue.bytes];        }    }    return udid;}+ (BOOL)settUDIDToKeyChain:(NSString*)udid{    NSMutableDictionary *dictForAdd = [[NSMutableDictionary alloc] init];    [dictForAdd setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];    [dictForAdd setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier] forKey:(NSString *)kSecAttrDescription];    [dictForAdd setValue:@"UUID" forKey:(id)kSecAttrGeneric];    // Default attributes for keychain item.    [dictForAdd setObject:@"" forKey:(id)kSecAttrAccount];    [dictForAdd setObject:@"" forKey:(id)kSecAttrLabel];    // The keychain access group attribute determines if this item can be shared    // amongst multiple apps whose code signing entitlements contain the same keychain access group.    NSString *accessGroup = [NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];    if (accessGroup != nil)    {#if TARGET_IPHONE_SIMULATOR        // Ignore the access group if running on the iPhone simulator.        //        // Apps that are built for the simulator aren't signed, so there's no keychain access group        // for the simulator to check. This means that all apps can see all keychain items when run        // on the simulator.        //        // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the        // simulator will return -25243 (errSecNoAccessForItem).#else        [dictForAdd setObject:accessGroup forKey:(id)kSecAttrAccessGroup];#endif    }    const char *udidStr = [udid UTF8String];    NSData *keyChainItemValue = [NSData dataWithBytes:udidStr length:strlen(udidStr)];    [dictForAdd setValue:keyChainItemValue forKey:(id)kSecValueData];    OSStatus writeErr = noErr;    if ([SvUDIDTools getUDIDFromKeyChain]) {        // there is item in keychain        [SvUDIDTools updateUDIDInKeyChain:udid];        return YES;    }    else {          // add item to keychain        writeErr = SecItemAdd((CFDictionaryRef)dictForAdd, NULL);        if (writeErr != errSecSuccess) {            NSLog(@"Add KeyChain Item Error!!! Error Code:%d", writeErr);            return NO;        }        else {            NSLog(@"Add KeyChain Item Success!!!");            return YES;        }    }    return NO;}+ (BOOL)removeUDIDFromKeyChain{    NSMutableDictionary *dictToDelete = [[NSMutableDictionary alloc] init];    [dictToDelete setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];    NSData *keyChainItemID = [NSData dataWithBytes:kKeychainUDIDItemIdentifier length:strlen(kKeychainUDIDItemIdentifier)];    [dictToDelete setValue:keyChainItemID forKey:(id)kSecAttrGeneric];    OSStatus deleteErr = noErr;    deleteErr = SecItemDelete((CFDictionaryRef)dictToDelete);    if (deleteErr != errSecSuccess) {        NSLog(@"delete UUID from KeyChain Error!!! Error code:%d", deleteErr);        return NO;    }    else {        NSLog(@"delete success!!!");    }    return YES;}+ (BOOL)updateUDIDInKeyChain:(NSString*)newUDID{    NSMutableDictionary *dictForQuery = [[NSMutableDictionary alloc] init];    [dictForQuery setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];    NSData *keychainItemID = [NSData dataWithBytes:kKeychainUDIDItemIdentifier                                            length:strlen(kKeychainUDIDItemIdentifier)];    [dictForQuery setValue:keychainItemID forKey:(id)kSecAttrGeneric];    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecMatchCaseInsensitive];    [dictForQuery setValue:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];    NSDictionary *queryResult = nil;    CFTypeRef typeQuery = (__bridge CFTypeRef)queryResult;    SecItemCopyMatching((CFDictionaryRef)dictForQuery, &typeQuery);    if (queryResult) {        NSMutableDictionary *dictForUpdate = [[NSMutableDictionary alloc] init];        [dictForUpdate setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier] forKey:(NSString *)kSecAttrDescription];        [dictForUpdate setValue:keychainItemID forKey:(id)kSecAttrGeneric];        const char *udidStr = [newUDID UTF8String];        NSData *keyChainItemValue = [NSData dataWithBytes:udidStr length:strlen(udidStr)];        [dictForUpdate setValue:keyChainItemValue forKey:(id)kSecValueData];        OSStatus updateErr = noErr;        // First we need the attributes from the Keychain.        NSMutableDictionary *updateItem = [NSMutableDictionary dictionaryWithDictionary:queryResult];        // Second we need to add the appropriate search key/values.        // set kSecClass is Very important        [updateItem setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];        updateErr = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)dictForUpdate);        if (updateErr != errSecSuccess) {            NSLog(@"Update KeyChain Item Error!!! Error Code:%d", updateErr);            return NO;        }        else {            NSLog(@"Update KeyChain Item Success!!!");            return YES;        }    }    return NO;}
原创粉丝点击