适配IPv6遇到的坑,终极解决方案

6.1AppStore发布之后的应用要兼容IPv6。

然而我上个星期发布的版本并没有因为没兼容而被拒,这次提交却遇到IPv6兼容问。。。

 话不多说,上代码:

 +(NSString *) getIPWithHostName:(const NSString *)hostName
    {
    struct addrinfo * result;
     struct addrinfo * res;
    char ipv4[128];
    char ipv6[128];
    int error;
    BOOL IS_IPV6 = FALSE;
    bzero(&ipv4, sizeof(ipv4));
    bzero(&ipv4, sizeof(ipv6));

    error = getaddrinfo([hostName UTF8String], NULL, NULL, &result);
    if(error != 0) {
    NSLog(@"error in getaddrinfo:%d", error);
    return nil;
    }
     for(res = result; res!=NULL; res = res->ai_next) {
    char hostname[1025] = "";
    error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, 1025, NULL, 0, 0);
    if(error != 0) {
        NSLog(@"error in getnameifno: %s", gai_strerror(error));
        continue;
    }
    else {
        switch (res->ai_addr->sa_family) {
            case AF_INET:
                memcpy(ipv4, hostname, 128);
                break;
            case AF_INET6:
                memcpy(ipv6, hostname, 128);
                IS_IPV6 = TRUE;
            default:
                break;
        }
        NSLog(@"hostname: %s ", hostname);
    }
    }
    freeaddrinfo(result);
    if(IS_IPV6 == TRUE) return [NSString stringWithUTF8String:ipv6];
    return [NSString stringWithUTF8String:ipv4];
    }

这段代码即判断了是否IPv6环境并解析域名获得了IP地址。

测试

首先得配置IPv6网络环境,至于如何配置,自行百度"如何搭建IPv6的测试环境"


然而配置成功后,用手机连接的WiFi DNS也是正确的,运行程序测试怎么不成功呢,找了好多资料,猜测是DNS解析出了问题。


那就换另一种方法配置IPv6:拔掉网线,用mac连接WiFi(没有WiFi可以用手机流量分享热点),然后在共享中用前一种方法配置IPv6(不知道具体是共享到电脑那个端口,索性全点上)记得选中"创建NAT64 网络"。这时直接通过模拟器测试succeed! 

测试成功了。你以为就没问题了?这里提交依然可能被拒,手机和 Mac 之间是 IPv6 没错,但 Mac 和你的服务器之间还是 IPv4 连接。


如果这项测试通过,可以说明:你的客户端应用在 IPv6 网络下,是(基本)没有问题的,但是无法验证你的服务器能够对 IPv6 网络做出正确的响应。然而,苹果审核的时候,却是要去 DNS 服务器询问你的服务器的 IPv6 地址,然后进行访问。如果查询不到 IPv6 地址,可能会进而询问 IPv4 地址,然后进行转换使用。苹果明确表示服务器不需要支持 IPv6,但是有一点苹果没有指出来,那就是,虽然你的服务器不用支持 IPv6,但是必须正确响应 IPv6 的 DNS 查询。
 

如何验证呢??使用以下命令即可:

$ dig +nocmd +nostats example.com AAAA

如果返回的 status 为 NOERROR, 那基本就没什么问题,但是一定要在多个网络环境下测试都通过才行。如果返回的是其他的响应,尤其是 SERVFAIL 的情况,那就基本杯具了。由于你已经验证了客户端没有问题,现在要做的,就是催着你的运维、后台啥的,赶紧去改 DNS 配置,直到稳定返回 NOERROR 为止。


 


*****************2017/06/01更新 ************************

今天新换了域名,发现解析有问题了 更新一下代码

+ (NSString *)getIPWithHostName:(NSString *)hostName {
    const char * c_ip = [hostName UTF8String];
    char * ipchar = calloc(hostName.length, sizeof(char));
    strcpy(ipchar, c_ip);
    
    struct addrinfo hints, *res, *res0;
    int error, s;
    const char * newChar = "No";
    
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_DEFAULT;
    
    error = getaddrinfo(ipchar, "http", &hints, &res0);
    free(ipchar);
    
    if (error) {
        errx(1, "%s", gai_strerror(error));
        /*NOTREACHED*/
    }
    s = -1;
    
    static struct sockaddr_in6 * addr6;
    static struct sockaddr_in * addr;
    //    NSString * NewStr = NULL;
    char ipbuf[32];
    
    NSString * TempA = NULL;
    
    for (res = res0; res; res = res->ai_next) {
        
        if (res->ai_family == AF_INET6) {
            addr6 =( struct sockaddr_in6*)res->ai_addr;
            newChar = inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, sizeof(ipbuf));
            TempA = [[NSString alloc] initWithCString:(const char*)newChar
                                             encoding:NSASCIIStringEncoding];
            
            //            address = TempA;
            
            //            NSString * TempB = [NSString stringWithUTF8String:"&&ipv6"];
            //
            //            NewStr = [TempA stringByAppendingString: TempB];
            printf("%s\n", newChar);
            
        } else {
            addr =( struct sockaddr_in*)res->ai_addr;
            newChar = inet_ntop(AF_INET, &addr->sin_addr, ipbuf, sizeof(ipbuf));
            TempA = [[NSString alloc] initWithCString:(const char*)newChar
                                             encoding:NSASCIIStringEncoding];
            //            NSString * TempB = [NSString stringWithUTF8String:"&&ipv4"];
            //
            //            NewStr = [TempA stringByAppendingString: TempB];
            printf("%s\n", newChar);
        }
        
        break;
    }
    
    freeaddrinfo(res0);
    
    return TempA;
}

 



  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值