我在iOS上浏览了类似这样的东西,发现了像这样的问题(Swift – Get device’s IP Address),所以我相信它可以做到,但我不清楚怎么办?
我怎样才能做到这一点?
编辑06/07/2018
@mdeora建议从http://www.software7.com/blog/programmatically-query-specific-dns-servers-on-ios/开始解决
此解决方案有效,但仅限于我使用IPv4 DNS,例如Google的“8.8.8.8”.如果我尝试使用IPv6 DNS 2001:4860:4860 :: 8888,我什么都没得到.
我设法改变转换:
voID setup_dns_server(res_state res,const char *dns_server){ res_ninit(res); struct in_addr addr;// int returnValue = inet_aton(dns_server,&addr); inet_pton(AF_INET6,dns_server,&addr); // for IPv6 conversion res->nsaddr_List[0].sin_addr = addr; res->nsaddr_List[0].sin_family = AF_INET; res->nsaddr_List[0].sin_port = htons(NS_DEFAulTPORT); res->nscount = 1;};
但仍然有这个问题:
voID query_ip(res_state res,const char *host,char ip[]){ u_char answer[NS_PACKETSZ];//NS_IN6ADDRSZ NS_PACKETSZ int len = res_nquery(res,host,ns_c_in,ns_t_a,answer,sizeof(answer)); ns_msg handle; ns_initparse(answer,len,&handle); if(ns_msg_count(handle,ns_s_an) > 0) { ns_rr rr; if(ns_parserr(&handle,ns_s_an,&rr) == 0) { strcpy(ip,inet_ntoa(*(struct in_addr *)ns_rr_rdata(rr))); } }}
len得到-1.从我收集的内容来看,我似乎需要为IPv6配置res_state.
解决方法 这里我上面提到的博客中的代码稍微适应了使用IPv6.适应setup_dns_server
首先我们可以从setup_dns_server的更改开始:
voID setup_dns_server(res_state res,const char *dns_server) { struct in6_addr addr; inet_pton(AF_INET6,&addr); res->_u._ext.ext->nsaddrs[0].sin6.sin6_addr = addr; res->_u._ext.ext->nsaddrs[0].sin6.sin6_family = AF_INET6; res->_u._ext.ext->nsaddrs[0].sin6.sin6_port = htons(NS_DEFAulTPORT); res->nscount = 1;}
添加__res_state_ext
由于缺少struct __res_state_ext,因此无法编译.不幸的是,这种结构位于私有头文件中.
但是这个的定义可以从这里得出:
https://opensource.apple.com/source/libresolv/libresolv-65/res_private.h.auto.html:
struct __res_state_ext { union res_sockaddr_union nsaddrs[MAXNS]; struct sort_List { int af; union { struct in_addr ina; struct in6_addr in6a; } addr,mask; } sort_List[MAXRESolVSORT]; char nsuffix[64]; char bsuffix[64]; char nsuffix2[64];};
可以添加结构,例如在文件的顶部.
适应resolveHost
这里的更改包括更长的ip缓冲区(INET6_ADDRSTRLEN). res_ninit从setup_dns_server移动到此方法,现在与res_ndestroy匹配.
+ (Nsstring *)resolveHost:(Nsstring *)host usingDNSServer:(Nsstring *)dnsServer { struct __res_state res; char ip[INET6_ADDRSTRLEN]; memset(ip,'voID query_ip(res_state res,char ip[]) { u_char answer[NS_PACKETSZ]; int len = res_nquery(res,ns_t_aaaa,&rr) == 0) { inet_ntop(AF_INET6,ns_rr_rdata(rr),ip,INET6_ADDRSTRLEN); } }}',sizeof(ip)); res_ninit(&res); setup_dns_server(&res,[dnsServer cStringUsingEnCoding:NSASCIIStringEnCoding]); query_ip(&res,[host cStringUsingEnCoding:NSUTF8StringEnCoding],ip); res_ndestroy(&res); return [[Nsstring alloc] initWithCString:ip enCoding:NSASCIIStringEnCoding];}
检索IPv6地址
如果您只想为DNS服务器使用IPv6地址,则上述更改已足够.因此,在query_ip中,如果您仍想检索IPv4地址,则无需进行任何更改.
如果您还想从DNS服务器检索IPv6地址,您可以这样做:
Nsstring *resolved = [ResolveUtil resolveHost:@"www.Google.com" usingDNSServer:@"2001:4860:4860::8888"];NSLog(@"%@",resolved);
请注意:我们在这里使用ns_t_aaaa来获取AAAA资源记录(quad-A记录),因为在DNS中它指定了IPv6地址和主机名之间的映射.对于许多主机,没有这样的四A记录,这意味着您可以通过IPv4访问它们.
呼叫
你会称它为例如像这样:
结果如下:
放弃
这些只是简单的示例调用,演示了函数的基本用法.没有错误处理.
总结以上是内存溢出为你收集整理的iOS:如何指定用于将主机名解析为IP地址的DNS?全部内容,希望文章能够帮你解决iOS:如何指定用于将主机名解析为IP地址的DNS?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)