Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
6.  Socket Interfaces Datagram Sockets  Previous   Contents   Next 
   
 

The following sample code shows how to read an Internet call by creating a socket, binding a name to the socket, and then reading from the socket.


Example 6-5 Reading Internet Family Datagrams

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
/*
 * This program creates a datagram socket, binds a name to it, then
 * reads from the socket.
 */
 main()
{
    int sock, length;
    struct sockaddr_in6 name;
    char buf[1024];
    /* Create socket from which to read. */
    sock = socket(AF_INET6, SOCK_DGRAM, 0);
    if (sock == -1) {
        perror("opening datagram socket");
        exit(1);
   }
   /* Create name with wildcards. */
   bzero (&name, sizeof (name));
   name.sin6_family = AF_INET6;
   name.sin6_addr = in6addr_any;
   name.sin6_port = 0;
   if (bind (sock, (struct sockaddr *)&name, sizeof (name)) == -1) {
       perror("binding datagram socket");
       exit(1);
   }
   /* Find assigned port value and print it out. */
   length = sizeof(name);
   if (getsockname(sock,(struct sockaddr *) &name, &length)
         == -1) 	{
       perror("getting socket name");
       exit(1);
   }
   printf("Socket port #%d\n", ntohs(name.sin6_port));
   /* Read from the socket. */
   if (read(sock, buf, 1024) == -1 )
       perror("receiving datagram packet");
   /* Assumes the data is printable */
   printf("-->%s\n", buf);
   close(sock);
   exit(0);
}

Standard Routines

This section describes the routines that you can use to locate and construct network addresses. Unless otherwise stated, interfaces presented in this section apply only to the Internet family.

Locating a service on a remote host requires many levels of mapping before the client and server communicate. A service has a name for human use. The service and host names must translate to network addresses. Finally, the network address must be usable to locate and route to the host. The specifics of the mappings can vary between network architectures. Preferably, a network does not require that hosts be named, thus protecting the identity of their physical locations.

Standard routines map host names to network addresses, network names to network numbers, protocol names to protocol numbers, and service names to port numbers. They also indicate the appropriate protocol to use in communicating with the server process. The file netdb.h must be included when using any of these routines.

Host and Service Names

The interfaces getaddrinfo(3SOCKET), getnameinfo(3SOCKET), and freeaddrinfo(3SOCKET) provide a simplified way to translate between the names and addresses of a service on a host. For IPv6, you can use these interfaces instead of calling getipnodebyname(3SOCKET) and getservbyname(3SOCKET), and then having to figure out how to combine the addresses. Similarly, for IPv4, you can use these interfaces instead of gethostbyname(3NSL) and getservbyname(3SOCKET). Both IPv6 and IPv4 addresses are handled transparently.

The getaddrinfo(3SOCKET) routine returns the combined address and port number of the specified host and service names. Because the information returned by getaddrinfo(3SOCKET) is dynamically allocated, it must be freed by freeaddrinfo(3SOCKET) to prevent memory leaks. getnameinfo(3SOCKET) returns the host and services names associated with a specified address and port number. Call gai_strerror(3SOCKET) to print error messages based on the EAI_xxx codes returned by getaddrinfo(3SOCKET) and getnameinfo(3SOCKET).

An example of using getaddrinfo(3SOCKET) follows.

    struct addrinfo         *res, *aip;
    struct addrinfo         hints;
    int                     sock = -1;
    int                     error;

    /* Get host address.  Any type of address will do. */
    bzero(&hints, sizeof (hints));
    hints.ai_flags = AI_ALL|AI_ADDRCONFIG;
    hints.ai_socktype = SOCK_STREAM;

    error = getaddrinfo(hostname, servicename, &hints, &res);
    if (error != 0) {
      (void) fprintf(stderr, "getaddrinfo: %s for host %s service %s\n",
      gai_strerror(error), hostname, servicename);
     return (-1);
    }
 

After processing the information returned by getaddrinfo(3SOCKET) in the structure pointed to by res, the storage should be released by freeaddrinfo(res).

The getnameinfo(3SOCKET) routine is particularly useful in identifying the cause of an error, as in the following example:

    struct sockaddr_storage faddr;
    int                     sock, new_sock, sock_opt;
    socklen_t               faddrlen;
    int                     error;
    char                    hname[NI_MAXHOST];
    char                    sname[NI_MAXSERV];

     ...
         faddrlen = sizeof (faddr);
         new_sock = accept(sock, (struct sockaddr *)&faddr, &faddrlen);
         if (new_sock == -1) {
             if (errno != EINTR && errno != ECONNABORTED) {
                 perror("accept");
             }
             continue;
         }        
         error = getnameinfo((struct sockaddr *)&faddr, faddrlen, hname, 
                     sizeof (hname), sname, sizeof (sname), 0);
         if (error) {
           (void) fprintf(stderr, "getnameinfo: %s\n",
                       gai_strerror(error));
         } else {
             (void) printf("Connection from %s/%s\n", hname, sname);
         }

Host Names - hostent

An Internet host-name-to-address mapping is represented by the hostent structure as defined in gethostent(3NSL):

struct hostent {
	   char  *h_name;            /* official name of host */
	   char  **h_aliases;        /* alias list */
	   int   h_addrtype;         /* hostaddrtype(e.g.,AF_INET6) */
	   int   h_length;           /* length of address */
	   char  **h_addr_list;      /* list of addrs, null terminated */
};
/*1st addr, net byte order*/
#define h_addr h_addr_list[0]
 
 
 
  Previous   Contents   Next