Thread: gethostbyname and structs

  1. #1
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92

    gethostbyname and structs

    I'm trying to some something that should be pretty simple; use the gethostbyname()-function. My problem is that I don't understand what the struct is doing, and why I need it. Structs in general makes me confused. For example, I tried with this code:

    Code:
    #include <stdio.h>
    #include <netdb.h>
    
    extern int h_errno;
    
    int main() {
    
    	char *name = "192.168.0.1";
    	struct hostent *hp;
    	
    	if((hp = gethostbyname(name)) == NULL){
    		herror("gethostbyname");
    	}
    	
    	return 0;
    }
    It compiles as it should, but I want to print out the name of the host - but where is it stored? I know the hostent struct has a field called '*h_name', which holds the name of the host/server. But I can't print out the name by doing 'hp.h_name' or by just trying to print out the variable 'name'. So my questions are; how does the info get into (or point to) 'h_name'? How do I use the struct? Do I have to declare the whole struct to use it?

    And, the declaration of the variable 'name', is it illigal? Do I use memory I haven't allocated?

  2. #2
    Has a Masters in B.S.
    Join Date
    Aug 2001
    Posts
    2,263
    ADVISORY: This users posts are rated CP-MA, for Mature Audiences only.

  3. #3
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    When you have a pointer to a structure you can access one of its member with the -> operator. This, and other features of structures, are explained in the C tutorial structures page. Therefore, to print out the name we can use:
    Code:
    printf("%s", hp->h_name);
    >> And, the declaration of the variable 'name', is it illigal? Do I use memory I haven't allocated? <<

    No, that declaration is fine. It allocates a character pointer and points it at a string literal. Since a string literal may be placed in read-only memory, you should not modify it. For example, running name[0] = 'a' may crash your program.

  4. #4
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92
    Isn't the -> and . equivalent? I always thought so at least.. I tried both in my code, and only the -> worked, as you suggested, anonytmouse. Thanks!

  5. #5
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    -> meant for pointers...
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  6. #6
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92
    I think I've misunderstood the function gethostbyname().. Whatever input I give the function, IP or domain name, it only returns the input. That can't be right, can it? The code is this:
    Code:
    #include <stdio.h>
    #include <netdb.h>
    #include <stdlib.h>
    
    extern int h_errno;
    
    int main(int argc, char *argv[]) {
    
    	struct hostent *host;
    	
    	if(argc != 2) {
    		printf("usage: %s <ip>\n", argv[0]);
    		exit(-1);
    	}
    
    	if((host = gethostbyname(argv[1])) == NULL) {
    		herror("ERROR");
    	}
    		
    	printf("hostname: %s\n", host->h_name);
    	return 0;
    }
    What function(s) can be used to retrieve the IP? I did a search with google, and found references to the struct in_addr several times, but what functions can that be used with?

  7. #7
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    somestruct->member is the same as (*somestruct).member
    If you understand what you're doing, you're not learning anything.

  8. #8
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    kristy, I suggest you read this sockets guide:
    http://www.ecst.csuchico.edu/~beej/guide/net/
    it's truly one of the best.


    the gethostbyname function does resolve the ip of given hostname (dns). but if you input it with ip, the function will return the same ip.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  9. #9
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92
    Quote Originally Posted by Devil Panther
    kristy, I suggest you read this sockets guide:
    http://www.ecst.csuchico.edu/~beej/guide/net/
    it's truly one of the best.
    Yeah, I probably should. Network programming tends to psyche me out though. Even the smallest programs are very advanced. I'm not very good with pointers yet, and strucs are, as already mentioned, even harder. I've been thinking about getting a book about network programming, but there's so many available that I haven't made up my mind yet. Thanks for the link, I have already taken a look at it (and I'll try to read more).

    the gethostbyname function does resolve the ip of given hostname (dns). but if you input it with ip, the function will return the same ip.
    Weird. My code posted above doesn't do that.

  10. #10
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    keep reading the guide... it has examples of both client and server programs, it's more than enough to help you master the feild.

    goodluck.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  11. #11
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    If you want to resolve an IP address to a host name, you can use gethostbyaddr. This function takes an IP address in the form of a structure known as struct in_addr. There is a function to convert a string IP address to a struct in_addr called inet_addr. Taking this information we can write some code to resolve an IP address to a host name:
    Code:
    struct in_addr addr; /* Structure to hold an IP address. */
    addr.s_addr = inet_addr("66.139.79.229"); /* Convert a string IP address to its numeric equivalent. */
    hp = gethostbyaddr(&addr, sizeof(addr), AF_INET);
    if (hp) printf("%s\n", hp->h_name);
    If you want to resolve a host name to an IP address you are on the right track with gethostbyname. This function returns one or more IP addresses, each in the form of a struct in_addr. There is a function to convert a struct in_addr to a string called inet_ntoa. Taking this knowledge we can write some code to resolve a host name to an IP address:
    Code:
    hp = gethostbyname("cboard.cprogramming.com");
    if (hp) printf("%s\n", inet_ntoa( *(struct in_addr*) hp->h_addr_list[0])); /* Print first address. */
    Many of the network functions are designed to work with different types of network addresses other than IPV4. This means that some confusing casts must be used.

  12. #12
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92
    The casting in the last code snippet screams confusion to me. I get that inet_ntoa() takes a struct of the type in_addr, but why the * both in front of the cast and inside the parentheses (*(struct in_addr*))?

    I read the sockets guide earlier today, but I'm still lost when it comes to the structs. I don't even get if the struct is the data type, or the type of the struct, for example in_addr, is the data type. Can someone clarify this?

    Thank you for your help, btw.

  13. #13
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    read the bottom lines of page 22 in the beej guide.
    it will explain the "weirdness" of this specific casting.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  14. #14
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92
    I did read it, and I didn't get it. I don't get why the *-operator is used twice..

    I tried to write some code (which I guess clearly shows I don't know what I'm doing!), and it fails on the bind procedure. What I want the app to do is to create a socket, and then get some info on the host. Should I perhaps use connect too? I guess the bind fails due to the server I'm testing it on (my own). Do I need to run a service on the port to be able to get any kind of response? Anyway, here's the code:
    Code:
    #include <stdio.h>
    #include <netdb.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define PORT 6891 // < 1024 = root only
    
    extern int errno;
    extern int h_errno;
    
    int main(int argc, char *argv[]) {
    	
    	char *ip;
    	int newsock, peer, peer_len;
    	struct hostent *host;
    	struct sockaddr_in address;
    	
    	if(argc != 2) {
    		printf("usage: %s <host or ip>\n", argv[0]);
    		exit(-1);
    	}
    	
    	/* if argument is a host, get the IP. if IP is supplied, it's ok! */
    	if((host = gethostbyname(argv[1])) == NULL) {
    		herror("ERROR on getting host:");
    		exit(-1);
    	} else {
    		/* get the IP from the host */
    		ip = inet_ntoa(*(struct in_addr*)host->h_addr_list[0]); 
    	}
    	
    	printf("%s\n", ip);
    	
    	/* AF_INET = ARPA Internet protocols */
    	if((newsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    		herror("ERROR (on socket)");
    		exit(-1);
    	}
    
    	/* setting up the struct */
    	address.sin_family = AF_INET;
    	address.sin_addr.s_addr = *ip; /* getting the IP into the struct */ /* WRONG ??? */
    	address.sin_port = htons(PORT); /* getting the port to connect to */
    	address.sin_family = AF_INET;  /* host byte order */
    	memset(&(address.sin_zero), '\0', 8);
    	
    	/* bind to the port with the descriptor */
    	if(bind(newsock, (struct sockaddr *)&address, sizeof(struct sockaddr)) == -1) {
    		herror("ERROR (on bind)");
    		exit(-1);
    	}
    	
    	peer_len = sizeof(address);
    	
    	/* get some info on the host */
    	if((peer = getpeername(newsock, (struct sockaddr *)&address, &peer_len)) == -1) {
    		herror("ERROR (on getpeername)");
    		exit(-1);
    	}
    	return 0;
    }

  15. #15
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    what kind of network application are you trying to write?
    is it a client or a server?

    in case of a client program, you don't need the bind, and you do need the connect.
    if you do decide to use bind in a client program, you bind it to a specific port from which it should connect.
    otherwise, you let the OS to allocate a port for this connection.


    Do I need to run a service on the port to be able to get any kind of response?
    if your client is trying to connect a port on server machine you need the port to be open, but in that case the
    program will fail on the connect call, and not the bind.
    remember: no listening port, no connection!
    Last edited by Devil Panther; 05-14-2005 at 04:00 PM.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

Popular pages Recent additions subscribe to a feed