1. 程式人生 > >關於iOS配置ipv6和ipv4地址不同時的處理辦法

關於iOS配置ipv6和ipv4地址不同時的處理辦法

當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 domain
static 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;
}



相關推薦

關於iOS配置ipv6ipv4地址同時處理辦法

當ipv6和ipv4地址不同時的處理: -(void)getHost{ if ([DeviceInfo isIpv6]) { return hostIpv6; } return hostIpv4; } -(void)get

HAproxy配置IPv6IPv4的互相代理實驗

這裡我們使用簡單的 httpd 服務進行測試。 實驗環境 序號 IPv4地址 IPv6地址 1 10.144.91.124 fd88:5110:a240::886:

ubuntu下100%成功安裝torch,同時配置cudacudnn(成功,則成仁)

總說這些更新不影響主體。所有更新附加在文章最後。 第一次更新: 內容:新增一些Torch7常用庫的安裝,時間:2017.3.20 第二次更新:內容:某些torch庫無法線上安裝,轉成離線安裝的方法,時間:2017.3.31 第三次更新:內容:針對安裝”cutorch”時出錯的問

用getaddrinfo()函式,通過主機名獲得ipv6ipv4地址

111111111111111 using the function "getaddrinfo()" to get the IP address from the hostname you provided; actually , the "getadrinfo()" function can get

第11章 拾遺4:IPv6IPv4共存技術(1)_雙棧技術6to4隧道技術

說明 images 測試結果 ges conf alt style dns服務 數據 6. IPv6和IPv4共存技術 6.1 雙棧技術 (1)雙協議主機的協議結構 (2)雙協議棧示意圖   ①雙協議主機在通信時首先通過支持雙協議的DNS服務器查詢與目的主機名對應的

第11章 拾遺5:IPv6IPv4共存技術(3)_NAT-PT技術【全書完】

cas 不知道 路由 共存 同時 種類型 並且 修改 添加 6.4 NAT-PT (1)NAT-PT和NAT的差別   ①NAT-PT(附帶協議轉換的網絡地址轉換)技術秉承NAT技術的思想,但在原理方面大有不同。   ②NAT-PT和NAT本質的區別在於應用場合的不同。

第11章 拾遺5:IPv6IPv4共存技術(2)_ISATAP隧道技術

6.3 ISATAP隧道技術 (1)基本概念   ①在一個IPv4網路中主機與路由器之間建立一條ISATAP隧道,以便讓該主機可以訪問IPv6網路中的資源。   ②條件:IPv4中的PC主機需要支援IPv4和IPv6雙棧協議,然後需要一臺支援ISATAP的路由器。該路由器可以在網路

第11章 拾遺5:IPv6IPv4共存技術(1)_雙棧技術6to4隧道技術

6. IPv6和IPv4共存技術 6.1 雙棧技術 (1)雙協議主機的協議結構 (2)雙協議棧示意圖   ①雙協議主機在通訊時首先通過支援雙協議的DNS伺服器查詢與目的主機名對應的IP地址。   ②再根據指定的IPv6或IPv4地址開始通訊。   ③Win2008

8.解析主機名對應的別名IPv4地址

使用gethostbyname解析主機名對應的別名和IPv4地址 #include <netdb.h> #include <stdio.h> #include <net

centos7配置hostnameip地址

主機名 退出 lur 主機 queue system def emc running 一、修改hostname 1、查看當前hostname [root@localhost~]# hostnamelocalhost 2、配置新主機名 [root@localhost~]# h

IPv6IPv4基本頭部格式

原帖:http://book.51cto.com/art/201204/329740.htm 根據IPv4報文中存在的問題,IPv6報文頭格式與IPv4相比進行了一些改動。IPv6頭部結構遵循以下新規則: 基本頭部的固定長度:IPv6的基本報文頭長度固定為40位元組

ipv6ipv4(1)

20174年7月5日 參考資料: 《Linux高效能伺服器程式設計》        linux-2.6.32原始碼 《TCP/IP詳解》(卷一)          網路程式設計最重要的一個環節就是要理清TCP/IP傳輸協議棧。而協議棧的學習自然的少不了最關鍵的一個環節就是

IP地址廣播地址在一個網段內時根據IP地址子網掩碼計算廣播地址

看TCP/IP詳解 卷1這部大作的時候,看到裡面計算廣播地址的方法,就在自己的機器 上測試了一下,結果遇到了一個小困難:我的機器上IP地址和廣播地址不在一個網段: 廣播地址就是把IP地址中主機號的那幾位設定為1,可是這裡看起來確實都設定為1了(廣播地址的最後一段為255)

mybatis學習筆記(3)—資料庫bean名稱一樣處理方案

之前寫的mybatis物件的bean物件和資料庫的物件名稱是對應的,然而再實際開發的過程有很多不一一對應的情況。就需要解決。 bean物件: package com.test.bean; /* * javabean 物件 */ public class order { pr

Docker Tomcat應用日誌時間容器時間一致解決辦法

Docker 宿主機、容器、Tomcat應用日誌時間不一致解決辦法 說明: 1.在docker容器和系統時間不一致是因為docker容器的原生時區為0時區,而國內系統為東八區。 2.還有容器中執行的java應用打出的日誌時間和通過date -R

iOS 子檢視超出父檢視響應解決辦法

父檢視中重寫該方法 Objective-C - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event { UIView * view = [super hitTe

hexo categoriestags頁面顯示解決辦法

方法一: scaffolds/draft.md --- title: {{ title }} tags: {{ tags }} --- scaffolds/post.md --- title

機器學習中樣本平衡處理辦法

   在機器學習任務中,我們經常會遇到這種困擾:資料不平衡問題。比如在廣告點選預估、反欺詐、風控裡面。 資料不平衡問題主要存在於有監督機器學習任務中。當遇到不平衡資料時,以總體分類準確率為學習目標的傳統分類演算法會過多地關注多數類,從而使得少數類樣本的分類效能下降。絕大

centos配置ipv6地址

linux 網站 網卡 賬號 default 首先打開網站註冊一個賬號:http://www.tunnelbroker.net創建一個ipv6的地址:首先打開linux對ipv6的支持:#vi /etc/sysconfig/network NETWORKING_IPV6=yes IPV6_

Cisco思科IOS配置控制臺Console口遠程虛擬終端以及enable使能登錄密碼

cisco 遠程登錄 配置密碼 1、設置控制臺Console口密碼Router(config)#line console 0 #進入控制臺口Router(config-line)#login #允許口令登錄Router(config-line)#password xxx #登錄口令xx