iOS 应用将适应新的的IPv6-only网络 -解决方案

苹果公司还称“在WWDC 2015上,我们宣布iOS 9开始向IPv6-only网络服务过渡。自2016年6月1日起,开发者所有提交至App Store的应用必须支持IPv6-only网络。由于大部分现有应用程序已经通过NSURLSession和CFNetwork APIs兼容该协议,因此这些应用无需做出调整。但如果你依然使用IPv4 API的或者硬件编码IP地址,那么你需要手动调整应用代码来适应新变化。”

  除此之外苹果还提供了相关资料,帮助开发者开始向已经添加了对IPv6-only网络的支持过渡,其中包括了WWDC 2015大会期间的开发者文档等

 [摘录自:http://mt.sohu.com/20160520/n450596544.shtml]


一般的http请求不受影响,但如果使用socket等则需要调整.经测试,目前支付宝,微信均在ipv6下不能正常访问网络.QQ客户端可以.

由于公司项目中使用了CocoaAsyncSocket,经测试,公司的app在ipv6下不能使用.


解决方案:针对ios9做单独处理.

经修改后,测试ios9可以正常使用.



下面是修改:

1,AFNetworkReachabilityManager

+ (instancetype)manager
{
//#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
//    struct sockaddr_in6 address;
//    bzero(&address, sizeof(address));
//    address.sin6_len = sizeof(address);
//    address.sin6_family = AF_INET6;
//#else
//    
//    struct sockaddr_in address;
//    bzero(&address, sizeof(address));
//    address.sin_len = sizeof(address);
//    address.sin_family = AF_INET;
//#endif
    
    
    if (IOS9)
    {
        struct sockaddr_in6 address;
        bzero(&address, sizeof(address));
        address.sin6_len = sizeof(address);
        address.sin6_family = AF_INET6;
        return [self managerForAddress:&address];
    }
    else
    {
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_len = sizeof(address);
        address.sin_family = AF_INET;
        return [self managerForAddress:&address];
    }
}


2,GCDAsyncSocket使用

GCDAsyncSocket *socketTest = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
if(IOS9)
{
   socketTest.IPv4PreferredOverIPv6 = NO;
}
[socketTest connectToHost:@"xxx.xxx.xxx.xxx" onPort:xxx withTimeout:20 error:nil];

3,GCDAsyncSocket.m

+ (NSMutableArray *)lookupHost:(NSString *)host port:(uint16_t)port error:(NSError **)errPtr
{
	LogTrace();
	
	NSMutableArray *addresses = nil;
	NSError *error = nil;
	
	if ([host isEqualToString:@"localhost"] || [host isEqualToString:@"loopback"])
	{
		// Use LOOPBACK address
		struct sockaddr_in nativeAddr4;
		nativeAddr4.sin_len         = sizeof(struct sockaddr_in);
		nativeAddr4.sin_family      = AF_INET;
		nativeAddr4.sin_port        = htons(port);
		nativeAddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
		memset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero));
		
		struct sockaddr_in6 nativeAddr6;
		nativeAddr6.sin6_len        = sizeof(struct sockaddr_in6);
		nativeAddr6.sin6_family     = AF_INET6;
		nativeAddr6.sin6_port       = htons(port);
		nativeAddr6.sin6_flowinfo   = 0;
		nativeAddr6.sin6_addr       = in6addr_loopback;
		nativeAddr6.sin6_scope_id   = 0;
		
		// Wrap the native address structures
		
		NSData *address4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];
		NSData *address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
		
		addresses = [NSMutableArray arrayWithCapacity:2];
		[addresses addObject:address4];
		[addresses addObject:address6];
	}
	else
	{
		NSString *portStr = [NSString stringWithFormat:@"%hu", port];
		
		struct addrinfo hints, *res, *res0;
		
		memset(&hints, 0, sizeof(hints));
		hints.ai_family   = PF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		
		int gai_error = getaddrinfo([host UTF8String], [portStr UTF8String], &hints, &res0);
		
		if (gai_error)
		{
			error = [self gaiError:gai_error];
		}
		else
		{
			NSUInteger capacity = 0;
			for (res = res0; res; res = res->ai_next)
			{
				if (res->ai_family == AF_INET || res->ai_family == AF_INET6) {
					capacity++;
				}
			}
			
			addresses = [NSMutableArray arrayWithCapacity:capacity];
			
            for (res = res0; res; res = res->ai_next)
            {
                if (res->ai_family == AF_INET)
                {
                    // Found IPv4 address.
                    // Wrap the native address structure, and add to results.
                    
                    if (((struct sockaddr_in *)res->ai_addr)->sin_port == 0)
                        ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(port);
                    NSData *address4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
                    [addresses addObject:address4];
                }
                else if (res->ai_family == AF_INET6)
                {
                    // Found IPv6 address.
                    // Wrap the native address structure, and add to results.
                    
                    struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)res->ai_addr;
                    sockaddr->sin6_port = htons(port);
                    
                    NSData *address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
                    [addresses addObject:address6];
                    
//                    if (((struct sockaddr_in6 *)res->ai_addr)->sin6_port == 0)
//                        ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = htons(port);
//                    NSData *address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
//                    [addresses addObject:address6];
                }
            }

			freeaddrinfo(res0);
			
			if ([addresses count] == 0)
			{
				error = [self gaiError:EAI_FAIL];
			}
		}
	}
	
	if (errPtr) *errPtr = error;
	return addresses;
}




相关资料:

CocoaAsyncSocket相关解决方案:https://github.com/robbiehanson/CocoaAsyncSocket/issues/429

apple开发文档:https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html
















 



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值