美文网首页iOS网络『技术栈』iOS
iOS开发之-- DNS解析(网络切换的问题解决)

iOS开发之-- DNS解析(网络切换的问题解决)

作者: 树下老男孩 | 来源:发表于2015-06-18 16:11 被阅读13743次

    上次提到过由于电信的问题需要自己手动去解析dns,这里介绍的是如何拦截
    每一个请求做解析,但是没有说具体的解析方法,下面简单的记录一下:

    • res_query方法
    int res_query(char *domain_name, int class, int type, char *answer_buffer, int answer_buffer_length)
    

    这是比较常见的系统调用,使用该方法的时候需要在Xcode中添加libresolv.dylib,然后包含resolv.h头文件即可,具体代码如下:

        unsigned char res[512];
        int nBytesRead = 0;
        
        //调用系统方法
        nBytesRead = res_query("www.baidu.com", ns_c_in, ns_t_a, res, sizeof(res));
        
        ns_msg handle;
        ns_initparse(res, nBytesRead, &handle);
        
        NSMutableArray *ipList = nil;
        int msg_count = ns_msg_count(handle, ns_s_an);
        if (msg_count > 0) {
            ipList = [[NSMutableArray alloc] initWithCapacity:msg_count];
            for(int rrnum = 0; rrnum < msg_count; rrnum++) {
                ns_rr rr;
                
                //解析结果
                if(ns_parserr(&handle, ns_s_an, rrnum, &rr) == 0) {
                    char ip1[16];
                    strcpy(ip1, inet_ntoa(*(struct in_addr *)ns_rr_rdata(rr)));
                    NSString *ipString = [[NSString alloc] initWithCString:ip1 encoding:NSASCIIStringEncoding];
                    if (![ipString isEqualToString:@""]) {
                        
                        //将提取到的IP地址放到数组中
                        [ipList addObject:ipString];
                    }
                }
            }
        }
        
    

    然而该方法有一个问题,在网络从2/3G和WI-FI之间切换的时候,该方法经常不能正常工作,或者需要等待较长的时间,

    • gethostbyname
    struct hostent *gethostbyname(const char *hostName);
    

    具体代码如下:

        struct hostent *host = gethostbyname("www.google.com.hk");
        
        struct in_addr **list = (struct in_addr **)host->h_addr_list;
        
        //获取IP地址
        NSString *ip= [NSString stringWithCString:inet_ntoa(*list[0]) encoding:NSUTF8StringEncoding];
    
        NSLog(@"ip address is : %@",ip);
    

    该方法在碰到切换网络的时候,出现失败的情况比上面的方法好多了,但偶尔也还是会出现,是时候采用苹果自己的方法了。

    • CFHostStartInfoResolution
    Boolean CFHostStartInfoResolution (CFHostRef theHost, CFHostInfoType info, CFStreamError *error);
    

    具体实现方法如下:

        Boolean result,bResolved;
        CFHostRef hostRef;
        CFArrayRef addresses = NULL;
    
        CFStringRef hostNameRef = CFStringCreateWithCString(kCFAllocatorDefault, "www.google.com.hk", kCFStringEncodingASCII);
        
        hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostNameRef);
        if (hostRef) {
            result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL);
            if (result == TRUE) {
                addresses = CFHostGetAddressing(hostRef, &result);
            }
        }
        bResolved = result == TRUE ? true : false;
        
        if(bResolved)
        {
            struct sockaddr_in* remoteAddr;
            for(int i = 0; i < CFArrayGetCount(addresses); i++)
            {
                CFDataRef saData = (CFDataRef)CFArrayGetValueAtIndex(addresses, i);
                remoteAddr = (struct sockaddr_in*)CFDataGetBytePtr(saData);
                
                if(remoteAddr != NULL)
                {
                    //获取IP地址
                    char ip[16];
                    strcpy(ip, inet_ntoa(remoteAddr->sin_addr));
                }
            }
        }
        CFRelease(hostNameRef);
        CFRelease(hostRef);
    

    具体的demo可以到这里看看

    相关文章

      网友评论

      • 做一个有爱的伸手党:很厉害 虽然 我还没用过
        毛癫子:分享iOS开发的知识,解决大家遇到的问题,欢迎大家投稿~这是小编的一个IOS开发交流群:714042473。
      • 不喜欢说话的小张同学:ipv6会不会出问题😳
        毛癫子:分享iOS开发的知识,解决大家遇到的问题,欢迎大家投稿~这是小编的一个IOS开发交流群:714042473。
      • 90dd918e6cd2:appStore 有个DNS浏览器可以设置Host,是怎么做的呢?
      • 萧城x:3g wifi 切换 总有一种网络 访问域名的时候 出现 未能访问指定主机的服务器
      • coderYL:楼主,用AFNetworking发送请求时,域名的解析时间和结果(成功还是失败)可以得到么?
      • sdupidBoby:我这里正好出现了和楼主相反的情况,安卓的拉取速度很快几十毫秒,iOS则经常超时? 有什么建议吗
        Peter818:我也是,我的app在iphone上移动4G网络,各种超时,用电信联通和WiFi都毫无问题,安卓上移动4G网络也是秒杀,真是郁闷透了
      • Maple_chang:CFHostStartInfoResolution 这个方法是异步执行吗?还是可以同步等待获取的IP数据?
      • Bob林:dns 的响应时间怎么获取的
        喵喵枫雪:同问啊!
        吃饱了不会饿:我也想知道这个问题,楼主有解决方案么?
        afa19264386b:@Bob林 你找到方法了吗?
      • 279532b6e067:gethostbyname 项目中遇到过解析特别慢的情况;可用以getaddrinfo代替;当然做好用CFHostStartInfoResolution这个是异步的,调用完立即返回这个方法CFHostGetAddressing应该在CFHostSetClient()回调方法里调用,另外调用CFHostStartInfoResolution之前要加入runloop中CFHostScheduleWithRunLoop
      • iVikings:你好,请问下你这个方法可以做DNS拦截处理么?
        酷酷的哀殿:@Only在乎n1 没有使用 `-stopLoading` 方法?
        iVikings:@酷酷的哀殿 嗯,我解决了,谢谢哈,目前遇到了一个问题,在iOS8上,劫持SDWebImage下载图片会循环下载几次,滑动列表的时候,取消了上一次的下载导致的,还不知道怎么解决好
        酷酷的哀殿:@Only在乎n1 可以通过 NSURLProtocol 拦截 NSURLConnection,NSURLSession或者AFNetworking 发起的请求,并修改域名为 IP

      本文标题:iOS开发之-- DNS解析(网络切换的问题解决)

      本文链接:https://www.haomeiwen.com/subject/hnesqttx.html