Socket applications often need to convert hostnames like google.com to their corresponding ip address. This is done through dns requests.
The socket api in linux provides functions like gethostbyname and getaddrinfo that can be used to perform the dns requests and get the ip address.
1. gethostbyname
The first method uses the traditional gethostbyname function to retrieve information about a hostname/domain name.
Code
#include<stdio.h> //printf #include<string.h> //memset #include<stdlib.h> //for exit(0); #include<sys/socket.h> #include<errno.h> //For errno - the error number #include<netdb.h> //hostent #include<arpa/inet.h> int hostname_to_ip(char * , char *); int main(int argc , char *argv[]) { if(argc <2) { printf("Please provide a hostname to resolve"); exit(1); } char *hostname = argv[1]; char ip[100]; hostname_to_ip(hostname , ip); printf("%s resolved to %s" , hostname , ip); printf("\n"); } /* Get ip from domain name */ int hostname_to_ip(char * hostname , char* ip) { struct hostent *he; struct in_addr **addr_list; int i; if ( (he = gethostbyname( hostname ) ) == NULL) { // get the host info herror("gethostbyname"); return 1; } addr_list = (struct in_addr **) he->h_addr_list; for(i = 0; addr_list[i] != NULL; i++) { //Return the first one; strcpy(ip , inet_ntoa(*addr_list[i]) ); return 0; } return 1; }
Compile and Run
$ gcc hostname_to_ip.c && ./a.out www.google.com www.google.com resolved to 74.125.235.16 $ gcc hostname_to_ip.c && ./a.out www.msn.com www.msn.com resolved to 207.46.140.34 $ gcc hostname_to_ip.c && ./a.out www.yahoo.com www.yahoo.com resolved to 98.137.149.56
2. getaddrinfo
The second method uses the getaddrinfo function to retrieve information about a hostname/domain name. The getaddrinfo supports ipv6 better.
Code
#include<stdio.h> //printf #include<string.h> //memset #include<stdlib.h> //for exit(0); #include<sys/socket.h> #include<errno.h> //For errno - the error number #include<netdb.h> //hostent #include<arpa/inet.h> int hostname_to_ip(char * , char *); int main(int argc , char *argv[]) { if(argc <2) { printf("Please provide a hostname to resolve"); exit(1); } char *hostname = argv[1]; char ip[100]; hostname_to_ip(hostname , ip); printf("%s resolved to %s" , hostname , ip); printf("\n"); } /* Get ip from domain name */ int hostname_to_ip(char *hostname , char *ip) { int sockfd; struct addrinfo hints, *servinfo, *p; struct sockaddr_in *h; int rv; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6 hints.ai_socktype = SOCK_STREAM; if ( (rv = getaddrinfo( hostname , "http" , &hints , &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return 1; } // loop through all the results and connect to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { h = (struct sockaddr_in *) p->ai_addr; strcpy(ip , inet_ntoa( h->sin_addr ) ); } freeaddrinfo(servinfo); // all done with this structure return 0; }
Compile and Run
$ gcc hostname_to_ip.c && ./a.out www.google.com www.google.com resolved to 74.125.235.19 $ gcc hostname_to_ip.c && ./a.out www.yahoo.com www.yahoo.com resolved to 72.30.2.43 $ gcc hostname_to_ip.c && ./a.out www.msn.com www.msn.com resolved to 207.46.140.34
Explain the program
Thank you
anyone checking this code while running the output….
./a.out http://www.google.com
First of all, thanks for putting this tutorial up! I have used it as a basis for my next-gen code! Having stated that, let me show you how I have improved it.
Your getaddrinfo example continuously overwrites the “ip” C-string, until interating through the linked list is finished. Why not simply write to it once at end of the loop, if only getting the last entry is what you REALLY want, but that’s hardly useful! What you want is to make sure you’re using an IP that works!
“man getaddrinfo” from the terminal. On my OSX, it has nice example of iterating through the list and trying to test a socket connection for TCP. I have turned that example into usable code, integrated with your tutorial’s code:
http://pastebin.com/cfUw5sG6
For UDP you can do similar things by implementing a “test” msg for the server to receive and acknowledge with adaptive retransmission timeout.
Actually, having learned a little more, I’ve reverted to the newer inet_ntop. Simpler to use, I’m unsure if any power is lost from using it. I think it will be alright. Just thought I would leave evidence of my trail.
I noticed the same problem. I used a similar fix. If I did the example with http://www.google.com, the original code, printed “0.0.0.0”. It appears the last entry given by default name server is broken. The first entry is correct.
Thanks very much, while getaddinfo is not always work:
[yu@argcandargv-com gethostbyname]$ ./gethostbyname http://www.google.com
http://www.google.com resolved to 173.194.72.99
[yu@argcandargv-com gethostbyname]$ ./getaddrinfo http://www.google.com
http://www.google.com resolved to 0.0.0.0
[yu@argcandargv-com gethostbyname]$ ./getaddrinfo http://www.msn.com
http://www.msn.com resolved to 131.253.13.140
[yu@argcandargv-com gethostbyname]$
WHY?
try changing the following line
hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
to this
hints.ai_family = AF_INET;
Thank you, It works !
In the manual,
“The value AF_UNSPEC indicates that getaddrinfo() should return socket addresses for any address family (either IPv4 or IPv6, for example) that can be used with node and service.”
What is the basis of the judgments using IPv4 or IPv6?
The server support ipv6 ? or just my pc support IPv6?
for using ipv6, the server, your isp, your computer – all 3 should support ipv6
Thanks for your patient , while ,what makes me confuse is …
I mean,
if the ai_family’s value is “AF_UNSPEC”,
how the code judge using IPv4 or IPv6 ?
For example , if only my pc support IPv6 , will the code trying return the IPv6 address ?
i am not sure how AF_UNSPEC is supposed to behave exactly. It probably checks for both and based on the availability and priority it will return one of the addresses.
you can check out these links for more information on it
http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#ip4to6
http://stackoverflow.com/questions/8149601/what-would-be-the-disadvantages-risks-of-using-af-unspec
or call the getaddrinfo function like this
getaddrinfo( hostname , NULL , NULL , &servinfo);
that should give the correct ip of the hostname.
sir I have error like this—-
gethostbyname: unknown host
please resolve this..
check your internet connectivity by pinging the host first.
use the following command at terminal/console
ping hostname
if ping replies come correctly, then try the program again and let me know the results.
how to get our own ip address?? am getting only loopback address
for more information on how to get ip address of local interface check this post
https://www.binarytides.com/get-local-ip-c-linux/
its really helpful