我试图找到一种方法来获取我的DNS服务器ip,它出现在settings-> wi-fi-> details-> DNS下。我不知道苹果是否允许以编程方式获取此信息。
答案 0 :(得分:6)
这是(IMHO)一个更好的Swift3 +变体,它是dig for iOS使用的libresolv
的Swift包装器的摘录,并正确处理IPV6名称服务器:
open class Resolver {
fileprivate var state = __res_9_state()
public init() {
res_9_ninit(&state)
}
deinit() {
res_9_ndestroy(&state)
}
public final func getservers() -> [res_9_sockaddr_union] {
let maxServers = 10
var servers = [res_9_sockaddr_union](repeating: res_9_sockaddr_union(), count: maxServers)
let found = Int(res_9_getservers(&state, &servers, Int32(maxServers)))
// filter is to remove the erroneous empty entry when there's no real servers
return Array(servers[0 ..< found]).filter() { $0.sin.sin_len > 0 }
}
}
将res_9_sockaddr_union
转换为其字符串值可以通过以下方式完成:
extension Resolver {
public static func getnameinfo(_ s: res_9_sockaddr_union) -> String {
var s = s
var hostBuffer = [CChar](repeating: 0, count: Int(NI_MAXHOST))
len sinlen = socklen_t(s.sin.sin_len)
let _ = withUnsafePointer(to: &s) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
Darwin.getnameinfo($0, sinlen,
&hostBuffer, socklen_t(hostBuffer.count),
nil, 0,
NI_NUMERICHOST)
}
}
return String(cString: hostBuffer)
}
}
所有组合的都可以获得包含这样的服务器列表的String[]
:
let servers = Resolver().getservers().map(Resolver.getnameinfo)
答案 1 :(得分:4)
如果Swift不在您的项目中,则支持IPV6的ObjC版本:
#include <resolv.h>
#include <netdb.h>
@implementation DNSResolver {
res_state _state;
}
- (instancetype)init {
self = [super init];
if (self) {
_state = malloc(sizeof(struct __res_state));
if (EXIT_SUCCESS != res_ninit(_state)) {
free(_state);
return nil;
}
}
return self;
}
- (void)dealloc {
res_ndestroy(_state);
free(_state);
}
#pragma mark - Public
- (NSString *)getDNSAddressesCSV
{
NSMutableArray *addresses = [NSMutableArray new];
union res_sockaddr_union servers[NI_MAXSERV];
int serversFound = res_9_getservers(_state, servers, NI_MAXSERV);
char hostBuffer[NI_MAXHOST];
for (int i = 0; i < serversFound; i ++) {
union res_sockaddr_union s = servers[i];
if (s.sin.sin_len > 0) {
if (EXIT_SUCCESS == getnameinfo((struct sockaddr *)&s.sin, // Pointer to your struct sockaddr
(socklen_t)s.sin.sin_len, // Size of this struct
(char *)&hostBuffer, // Pointer to hostname string
sizeof(hostBuffer), // Size of this string
nil, // Pointer to service name string
0, // Size of this string
NI_NUMERICHOST)) { // Flags given
[addresses addObject:[NSString stringWithUTF8String:hostBuffer]];
}
}
}
return [addresses componentsJoinedByString:@","];
}
@end
答案 2 :(得分:3)
我在OS X上使用它并为我工作,(也链接到ibresolv.dylib)
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <resolv.h>
#include <dns.h>
- (NSString *) getDNSAddressesStr
{
NSMutableString *addressStr = [[NSMutableString alloc]initWithString:@"DNS Addresses \n"];
res_state res = malloc(sizeof(struct __res_state));
int result = res_ninit(res);
if ( result == 0 )
{
for ( int i = 0; i < res->nscount; i++ )
{
NSString *s = [NSString stringWithUTF8String : inet_ntoa(res->nsaddr_list[i].sin_addr)];
[addressStr appendFormat:@"%@\n",s];
NSLog(@"%@",s);
}
}
else
[addressStr appendString:@" res_init result != 0"];
return addressStr;
}
}
答案 3 :(得分:1)
我认为缺少free():
free(res);
ps for xCode 7 add&#34; libresolv.tbd&#34;到&#34;链接二进制库&#34;
答案 4 :(得分:0)
请参阅以下Swift代码以获取网站的DNS解析。一种方法使用CFHostStartInfoResolution
,而另一种方法使用gethostbyname
。
这两个API均支持全部/多个IP地址解析。
private func urlToIP_cfHostResolution(_ url: String) -> [String] {
var ipList: [String] = []
let host = CFHostCreateWithName(nil,url as CFString).takeRetainedValue()
CFHostStartInfoResolution(host, .addresses, nil)
var success: DarwinBoolean = false
if let addresses = CFHostGetAddressing(host, &success)?.takeUnretainedValue() as NSArray? {
for case let theAddress as NSData in addresses {
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
if getnameinfo(theAddress.bytes.assumingMemoryBound(to: sockaddr.self), socklen_t(theAddress.length),
&hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0 {
ipList.append(String(cString: hostname))
}
}
}
return ipList
}
此方法为["151.101.129.69", "151.101.1.69", "151.101.193.69", "151.101.65.69"]
返回www.stackoverflow.com
private func urlToIP_gethostbyname(_ url: URL) -> [String] {
var ipList: [String] = []
guard let hostname = url.host else {
return ipList
}
guard let host = hostname.withCString({gethostbyname($0)}) else {
return ipList
}
guard host.pointee.h_length > 0 else {
return ipList
}
var index = 0
while host.pointee.h_addr_list[index] != nil {
var addr: in_addr = in_addr()
memcpy(&addr.s_addr, host.pointee.h_addr_list[index], Int(host.pointee.h_length))
guard let remoteIPAsC = inet_ntoa(addr) else {
return ipList
}
ipList.append(String.init(cString: remoteIPAsC))
index += 1
}
return ipList
}
此方法还会为["151.101.129.69", "151.101.1.69", "151.101.193.69", "151.101.65.69"]
返回www.stackoverflow.com
希望这会有所帮助。
答案 5 :(得分:-1)
这是接受答案的Swift3变体:
func dnsServers() -> [in_addr_t] {
var result = __res_9_state()
guard res_9_ninit(&result) == 0 else { return [] }
let sockets = result.nsaddr_list // note: nsaddr_list is a tuple, not an array
let addresses = [sockets.0.sin_addr.s_addr, sockets.1.sin_addr.s_addr, sockets.2.sin_addr.s_addr]
let filtered = addresses.filter { $0 != nil }
return filtered
}
像往常一样,链接libresolv.9.tbd
并将#import <resolv.h>
添加到桥接标题