In general, to obtain the local DNS address, we use the following method.
Add the libresolv. TBD library to your system. We then introduce the following header files into the header file:
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <resolv.h>
#include <dns.h>
Copy the code
Then use, or adapt, the following code:
NSMutableArray *DNSList = [NSMutableArray array];
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)]; [DNSList addObject:s]; }}res_nclose(res);
free(res);
// dnsList is the DNS server address
Copy the code
Unfortunately, a friend of mine told me that using this code would cause a memory leak. I tried it out for myself, and it did. What’s wrong with it?
Lookup process
Int result = res_ninit(res); The memory created by this code has not been freed.
But I’ve already written res_nclose(res); Ah.
I had no choice but to click on the res_ninit page and search them one by one.
Finally, after a long search, I found an Oracle document.
There were a few notes in it that I found fascinating:
-
The res_ndestroy() function should be called to free memory allocated by res_ninit() after the last use of statp.
-
The res_nclose() function closes any open files referenced through statp.
-
The res_ndestroy() function calls res_nclose(), then frees any memory allocated by res_ninit() referenced through statp.
And this sample code:
#include <resolv.h>
#include <string.h>
int main(int argc, char **argv)
{
int len;
struct __res_state statp;
union msg {
uchar_t buf[NS_MAXMSG];
HEADER h;
} resbuf;
/* Initialize resolver */
memset(&statp, 0.sizeof(statp));
if (res_ninit(&statp) < 0) {
fprintf(stderr, "Can't initialize statp.\n");
return (1);
}
/* * Turning on DEBUG mode keeps this example simple, * without need to output anything. */
statp.options |= RES_DEBUG;
/* Search for A type records */
len = res_nsearch(&statp, "example.com", C_IN, T_A,
resbuf.buf, NS_MAXMSG);
if (len < 0) {
fprintf(stderr, "Error occured during search.\n");
return (1);
}
if (len > NS_MAXMSG) {
fprintf(stderr, "The buffer is too small.\n");
return (1);
}
/ *... Process the received answer ... * /
/* Cleanup */
res_ndestroy(&statp);
return (0);
}
Copy the code
This means:
- DNS information is stored in a STATP, which is created using res_ninit and then read from the crowd.
- The res_nclose function closes all open statp files, but does not free the memory. If you want to free memory while closing, you should use the res_ndestroy function.
The correct code
NSMutableArray *DNSList = [NSMutableArray array];
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)]; [DNSList addObject:s]; }}res_ndestroy(res);
free(res);
// dnsList is the DNS server address
Copy the code
reference
man pages section 3: Networking Library Functions