0

I am trying to resolve a NoIP hostname to an IP address so I can connect to it. Below is the code I am currently using, however e->h_name just returns the hostname string I provided to it, so it does not work. In Python, the gethostbyname function does it successfully so I am confused why it wouldn't work in C++.

void ResolveServerDNS(char* hostname) {
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);

    hostent* e = gethostbyname(hostname);

    std::cout << e->h_name << '\n';
}
  • On a side note, you should not be calling `WSAStartup()` inside of `ResolveServerDNS()`. You should be calling that once, such as at program startup. – Remy Lebeau Mar 16 '22 at 17:47
  • I am aware of this, I am not calling it inside of the function in my application. However when I ran the function alone just to test it, it provided an error because I did not call WSAStartup so I just put it in the function temporarily. –  Mar 16 '22 at 19:22
  • It should have been in your test app's `main()`/`WinMain()` function, not in your `ResolveServerDNS()` function. In any case, if you *did* call it inside your function like you showed, you would need to also call `WSACleanup()` inside your function, too. – Remy Lebeau Mar 16 '22 at 19:24

1 Answers1

1

To get the IP address, you need to use this instead:

printf("%s\n", inet_ntoa(*(struct in_addr *)host->h_addr_list[0]));

This is the hostent struct from https://learn.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-hostent

typedef struct hostent {
  char  *h_name;
  char  **h_aliases;
  short h_addrtype;
  short h_length;
  char  **h_addr_list;
} HOSTENT, *PHOSTENT, *LPHOSTENT;

In your function, it should be:

hostent *e = gethostbyname(hostname); 
std::cout << inet_ntoa(*(struct in_addr *)e->h_addr_list[0]) << '\n';

Let's test with this code : https://godbolt.org/z/zbTx7x3M7

Note: above is an example in case of gethostbyname() returning ok -> you need to take care if host is NULL & maybe DNS returns more IPs for one domain -> let's use a for loop to get all the IPs:

hostent *e = gethostbyname(hostname); 
for (int i = 0; e->h_addr_list[i] != NULL; i++) {
    std::cout << inet_ntoa(*(struct in_addr *)e->h_addr_list[i]) << '\n';
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
long.kl
  • 670
  • 4
  • 12
  • Thanks alot for this answer, I have used it in my application and it now works as intended! –  Mar 16 '22 at 16:22
  • 1
    "*let's use a `for` loop to get all the IPs*" - the `hostent::h_length` field is NOT the number of IPs in the list. It is the byte size of each IP (ie, `sizeof(in_addr)` for IPv4, `sizeof(in6_addr)` for IPv6). The list is NULL-terminated, so you need to loop until you reach an entry with a NULL pointer. I have corrected your example. – Remy Lebeau Mar 16 '22 at 17:42