First, the normal sequence (where a hostname such as "www.google.com" is given) is not
Code:
gethostbyname()
inet_ntoa()
but simply
because what is returned from
gethostbyname() is the address (or more than one address) already in the four-byte network-ordered format.
Second,
inet_ntoa() converts not from decimal-dotted format to four-byte network-ordered format, but the other way around. "n" stands for "network", and "a" stands for "ASCII".
inet_ntoa() goes from network to ASCII. What you want instead is
inet_aton().
Third, instead of using
inet_aton() and
inet_ntoa(), I strongly recommend you use
inet_pton() and
inet_ntop(). (The "p" stands for "presentation" format.) There are two reasons to do this.
- If you ever go back from 4-byte network addresses to printable dotted-decimal form, inet_ntop() is re-entrant. It stores the data in memory that you allocate, not in a static buffer. This will make your program easier to maintain if it gets much larger than you originally envisioned, which is something that happens often.
- You'll be that much closer to the day when you want to convert your program to be IPV6-aware.
The following code demonstrates it all:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc,
char **argv
)
{
char ntop_buffer[INET_ADDRSTRLEN];
struct sockaddr_in inxyz;
if(argc!=2)
{
fprintf(stderr,"we need one argument: a dotted decimal IP address\n");
exit(1);
}
if(inet_aton(argv[1],&inxyz.sin_addr)==0)
{
fprintf(stderr,"invalid address\n");
exit(1);
}
printf("Network-ordered address from inet_aton(), printed as a CPU-ordered integer:\n"
"0x%08X\n",
inxyz.sin_addr.s_addr
);
printf("Dotted decimal representation from inet_ntoa():\n%s\n",
inet_ntoa(inxyz.sin_addr)
);
if(inet_pton(AF_INET,argv[1],&inxyz.sin_addr)==0)
{
fprintf(stderr,"invalid address\n");
exit(1);
}
printf("Network-ordered address from inet_pton(), printed as a CPU-ordered integer:\n"
"0x%08X\n",
inxyz.sin_addr.s_addr
);
printf("Dotted decimal representation from inet_ntop():\n%s\n",
inet_ntop(AF_INET,&inxyz.sin_addr,ntop_buffer,INET_ADDRSTRLEN)
);
return 0;
} /* main() */
Another point: You can actually call
gethostbyname() instead if you want. It returns four-byte network-ordered addresses, and you can give it either "www.google.com" or "66.102.7.147". It will work either way.
Finally, you'll notice in the source code that I used variable
inxyz, not
in as you had in your example. When choosing the name of a variable, it's always better to choose something that's not a substring of some other identifier. Why? Because if you use your text editor to search for all instances of variable
in, for example, you'll also find many other uninteresting occurrences of "in".