C    IPv4 and IPv6 Sockets Programming Examples

This appendix contains annotated files for a sample client/server program. Clients send a request to the server and print the server's response. Servers listen for client requests, print the request, and send a response to the client.

Although the program is not a real world application, it is structured demonstrate the sequence and use of the various socket calls.

The information is organized as follows:

You can find these programs and a protocol-independent client in the/usr/examples/ipv6/network_programming directory. In addition, this section also contains sample output from these programs.

C.1    Programs Using AF_INET Sockets

This section contains a client and server program that use AF_INET sockets.

C.1.1    Client Program Using AF_INET Sockets

Example C-1 shows a sample client program that you can build, compile, and run on your system. The program sends a request to and receives a response from the system specified on the command line.

Example C-1:  Client Stub Routine

/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright (c) Compaq Computer Corporation, 2000            *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer  Corporation.  Possession, use,  duplication  or   *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>
 
#define SERVER_PORT	7639
#define CLIENT_PORT	7739
 
#define MAXBUFSIZE 4096
 
int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct sockaddr_in     serveraddr; [1]
    struct sockaddr_in     clientaddr;
    int             serveraddrlen;
    const char      *ap;
    const char      *request = "this is the client's request";
    struct hostent  *hp;
    char            *server;
 
    if (argc < 2) {
        printf("Usage: client <server>\n");
        exit(1);
    }
    server = argv[1];
 
    bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); [2]
    serveraddr.sin_family = AF_INET;
    if ((hp = gethostbyname(server)) == NULL) {  [3]
        printf("unknown host: %s\n", server);
        exit(2);
    }
    serveraddr.sin_port = htons(SERVER_PORT);
 
    while (hp->h_addr_list[0] != NULL) {
        if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { [4]
            perror("socket");
            exit(3);
        }
        memcpy(&serveraddr.sin_addr.s_addr, hp->h_addr_list[0],
                         hp->h_length);
 
        if (connect(s, (struct sockaddr *)&serveraddr, 
                          sizeof(serveraddr)) < 0) { [5]
            perror("connect");
            close(s);
            hp->h_addr_list++;
            continue;
        }
        break;
    }
    if (send(s, request, strlen(request), 0) < 0) { [6]
        perror("send");
        exit(5);
    }
    dcount = recv(s, databuf, sizeof(databuf), 0); [7]
    if (dcount < 0) {
        perror("recv");
        exit(6);
    }
    databuf[dcount] = '\0';
 
    hp = gethostbyaddr((char *)&serveraddr.sin_addr.s_addr, [8]
        sizeof(serveraddr.sin_addr.s_addr), AF_INET);
    ap = inet_ntoa(serveraddr.sin_addr);  [9]
    printf("Response received from");
    if (hp != NULL)
        printf(" %s", hp->h_name);
    if (ap != NULL)
        printf(" (%s)", ap);
    printf(": %s\n", databuf);
 
    close(s);
}
 
 

  1. Declares sockaddr_in structures. The use of this type of structure is dictated by the communication domain of the socket (AF_INET), which implies communication using the IPv4 protocol. [Return to example]

  2. Clears the server address and sets up server variables. The socket address for IPv4 communications is a 32-bit Internet address and a 16-bit port number. This will be the Internet address of the server and the port number on which it is listening. [Return to example]

  3. Obtain the server's IPv4 address. A call to gethostbyname returns IPv4 address only. [Return to example]

  4. Creates an AF_INET socket with a socket call. The socket type SOCK_STREAM is specified for TCP or connection-oriented communication. [Return to example]

  5. Connects to the server using the address in the sockaddr_in structure named serveraddr. [Return to example]

  6. Sends a request to the server. [Return to example]

  7. Receives a response from the server. [Return to example]

  8. Retrieves the server name using the address in the sockaddr_in structure named serveraddr. A call to gethostbyaddrexpects an IPv4 address as input. [Return to example]

  9. Convert the server's 32-bit IPv4 address to a dot-formatted Internet address text string. A call to inet_ntoa expects an IPv4 address as input. [Return to example]

C.1.2    Server Program Using AF_INET Sockets

Example C-2 shows a sample server program that you can build, compile, and run on your system. The program receives requests from and sends responses to client programs on other systems.

Example C-2:  Server Stub Routine

/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright (c) Compaq Computer  Corporation, 2000           *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer  Corporation.  Possession, use,  duplication  or   *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */
 
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>
 
#define SERVER_PORT	7639
#define CLIENT_PORT	7739
 
#define MAXBUFSIZE 4096
 
int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct sockaddr_in    serveraddr; [1]
    struct sockaddr_in    clientaddr;
    int                   clientaddrlen;
    struct hostent        *hp;
    const char            *ap;
    const char            *response = "this is the server's response";
    u_short               port;
 
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { [2]
        perror("socket");
        exit(1);
    }
 
    bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); [3]
    serveraddr.sin_family      = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); [4]
    serveraddr.sin_port        = htons(SERVER_PORT);
 
    if (bind(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { [5]
        perror("bind");
        exit(2);
    }
    if (listen(s, SOMAXCONN) < 0) { [6]
        perror("Listen");
        close(s);
        exit(3);
 
    while (1) {
        int new_s;
        clientaddrlen = sizeof(clientaddr);
        new_s = accept(s, (struct sockaddr *)&clientaddr, &clientaddrlen); [7]
 
        dcount = recv(new_s, databuf, sizeof(databuf), 0); [8]
        if (dcount <= 0) {
            perror("recv");
            close(new_s);
            continue;
        }
        databuf[dcount] = '\0';
        hp = gethostbyaddr((char *)&clientaddr.sin_addr.s_addr, [9]
            sizeof(clientaddr.sin_addr.s_addr), AF_INET);
        ap = inet_ntoa(clientaddr.sin_addr); [10]
        port = ntohs(clientaddr.sin_port);
        printf("Request received from");
        if (hp != NULL)
            printf(" %s", hp->h_name);
        if (ap != NULL)
            printf(" (%s)", ap);
        printf(" port %d \"%s\"\n", port, databuf);
 
        if (send(new_s, response, strlen(response), 0) < 0) { [11]
            perror("send");
            close(new_s);
            continue;
        }
        close(new_s);
    }
    close(s);
}
 
 

  1. Declares sockaddr_in structures. The use of this type of structure is dictated by the communication domain of the socket (AF_INET), which implies communication using the IPv4 protocol. [Return to example]

  2. Creates an AF_INET socket. The socket type SOCK_STREAM is specified for TCP or connection-oriented communication. [Return to example]

  3. Clears the server address and sets up server variables. The socket address for IPv4 communications is a 32-bit Internet address and a 16-bit port number. This will be the Internet address of the server and the port number on which it is listening. [Return to example]

  4. Sets the server address to the IPv4 wildcard address INADDR_ANY. This signifies any attached network interface on the system. [Return to example]

  5. Binds the server's address to the AF_INET socket. [Return to example]

  6. Listens on the socket for a connection. The server will queue up to SOMAXCONN pending connections while it finishes processing the previous accept call. See sys_attrs_socket(5) for more information on the socket subsystem kernel attributes. [Return to example]

  7. Accepts a connection on this socket. The accept call places the client's address in the sockaddr_in structure named clientaddr. [Return to example]

  8. Receives data from the client. [Return to example]

  9. Retrieves the client name using the address in the sockaddr_in structure named clientaddr. A call to gethostbyaddrexpects an IPv4 address as input. [Return to example]

  10. Converts the client's 32-bit IPv4 address to a dot-formatted Internet address text string. A call to inet_ntoa expects an IPv4 address as input. [Return to example]

  11. Sends a response to the client. [Return to example]

C.2    Programs Using AF_INET6 Sockets

This section contains a client and server program that use AF_INET6 sockets.

C.2.1    Client Program Using AF_INET6 Sockets

Example C-3 shows a sample client program that you can build, compile, and run on your system. The program sends a request to and receives a response from the system specified on the command line. All addresses are in IPv6 address format.

Example C-3:  Client Stub Routine

/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright (c) Compaq Computer Corporation, 2000            *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer Corporation.  Possession, use,  duplication  or    *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>
 
 
#define SERVER_PORT	7639
#define CLIENT_PORT	7739
 
#define MAXBUFSIZE 4096
 
int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct addrinfo *server_info; [1]
    struct addrinfo *cur_info;
    struct addrinfo hints;
    struct sockaddr_in6    serveraddr; [2]
    char            addrbuf[INET6_ADDRSTRLEN];
    char            node[MAXDNAME];
    char            service[MAXDNAME];
    int             ni;
    int             err;
    int             serveraddrlen;
    const char      *request = "this is the client's request";
    char            *server;
 
    if (argc < 2) {
        printf("Usage: client <server>\n");
        exit(1);
    }
    server = argv[1];
    bzero((char *) &hints, sizeof(hints)); [3]
    hints.ai_family = AF_INET6;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED;
 
    sprintf(service, "%d", SERVER_PORT);
 
    err = getaddrinfo(server, service, &hints, &server_info);  [4]
    if (err != 0) {
        printf("%s\n", gai_strerror(err));
            if (err == EAI_SYSTEM)
                perror("getaddrinfo");
            exit(2);
    }
    cur_info = server_info;
 
    while (cur_info != NULL) {
        if ((s = socket(cur_info->ai_family, cur_info->ai_socktype, 0)) < 0) { [5]
            perror("socket");
            freeaddrinfo(server_info);
            exit(3);
        }
        if (connect(s, cur_info->ai_addr, cur_info->ai_addrlen) <0 {  [6]
            close(s);
            cur_info = cur_info->ai_next;
            continue;
        }
        break;
    }
    freeaddrinfo(server_info); [7]
 
    if (send(s, request, strlen(request), 0) < 0) { [8]
        perror("send");
        exit(5);
    }
    dcount = recv(s, databuf, sizeof(databuf), 0); [9]
    if (dcount < 0) {
        perror("recv");
        exit(6);
    }
    databuf[dcount] = '\0';
    serveraddrlen = sizeof(serveraddr);
    if (getpeername(s, (struct sockaddr*) &serveraddr, &serveraddrlen) < 0) { [10]
        perror("getpeername");
        exit(7);
    }
    printf("Response received from");
    ni = getnameinfo((struct sockaddr*)&serveraddr, serveraddrlen, [11]
                        node, sizeof(node), NULL, 0, NI_NAMEREQD);
    if (ni == 0)
        printf(" %s", node);
    ni = getnameinfo((struct sockaddr*)&serveraddr, serveraddrlen, [12]
                        addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
    if (ni == 0)
        printf(" (%s)", addrbuf);
 
    printf(": %s\n", databuf);
 
    close(s);
}
 
 

  1. Declares addrinfo structures and the hints structure. [Return to example]

  2. Declares the sockaddr_in6 structure. The use of this type of structure is dictated by the communication domain of the socket (AF_INET6), which implies communication using the IPv6 protocol. If you wanted to write a protocol-independent program, you would declare a sockaddr_storage structure. [Return to example]

  3. Declares the address string buffer, node name string buffer, service name string buffer, error number variable, and server address length variable. [Return to example]

  4. Clears the hints structure and sets up hints variables. Thehints structure contains values that direct the getaddrinfo processing. In this case, AF_INET6 returns IPv6 addresses. The AI_ADDRCONFIG and AI_V4MAPPED values return AAAA records if an IPv6 address is configured, and if none are found, return A records if an IPv4 address is configured. See getaddrinfo(3) for more information on hints structure values. [Return to example]

  5. Obtains the server address. A call to getaddrinfo returns IPv6-formatted addresses in one or more structures of type addrinfo. [Return to example]

  6. Creates an AF_INET6 socket. The socket type is specified in the addrinfo structure. [Return to example]

  7. Connects to the server using the address in the addrinfo structure named cur_info. [Return to example]

  8. Frees all addrinfo structures. [Return to example]

  9. Sends a request to the server. [Return to example]

  10. Receives a response from the server. [Return to example]

  11. Obtains the address of the peer socket at the other end of the connection and stores the address in a sockaddr_in6 structure named serverinfo. [Return to example]

  12. Obtains the server's name with a call to getnameinfo using the address in the sockaddr_in6 structure named serveraddr. The NI_NAMEREQD flag directs the routine to return a host name for the given address. [Return to example]

  13. Obtains the server's numeric address value with a call to getnameinfo using the address in the sockaddr_in6 structure named serveraddr. The NI_NUMERICHOST flag directs the routine to return an address value for the given address. [Return to example]

C.2.2    Server Program Using AF_INET6 Sockets

Example C-4 shows a sample server program that you can build, compile, and run on your system. The program receives requests from and sends responses to client programs on other systems.

Example C-4:  Server Stub Routine

/*
 * *****************************************************************
 * *                                                               *
 * *    Copyright (c) Compaq Computer Corporation, 2000            *
 * *                                                               *
 * *   The software contained on this media  is  proprietary  to   *
 * *   and  embodies  the  confidential  technology  of  Compaq    *
 * *   Computer Corporation.  Possession, use,  duplication  or    *
 * *   dissemination of the software and media is authorized only  *
 * *   pursuant to a valid written license from Compaq Computer    *
 * *   Corporation.                                                *
 * *                                                               *
 * *   RESTRICTED RIGHTS LEGEND   Use, duplication, or disclosure  *
 * *   by the U.S. Government is subject to restrictions  as  set  *
 * *   forth in Subparagraph (c)(1)(ii)  of  DFARS  252.227-7013,  *
 * *   or  in  FAR 52.227-19, as applicable.                       *
 * *                                                               *
 * *****************************************************************
 */
 
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>
 
#define SERVER_PORT	7639
#define CLIENT_PORT	7739
 
#define MAXBUFSIZE 4096
 
int main (
    int argc,
    char **argv )
{
    int             s;
    char            databuf[MAXBUFSIZE];
    int             dcount;
    struct sockaddr_in6       serveraddr; [1]
    struct sockaddr_storage   clientaddr; [2]
    char                      addrbuf[INET6_ADDRSTRLEN];
    char                      node[MAXDNAME];
    char                      port[MAXDNAME];
    int                       err;
    int                       ni;
    int                       clientaddrlen;
    const char                *response = "this is the server's response";
 
    if ((s = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { [3]
        perror("socket");
        exit(1);
    }
 
    bzero((char *) &serveraddr, sizeof(struct sockaddr_in6)); [4]
    serveraddr.sin6_family      = AF_INET6;
    serveraddr.sin6_addr        = in6addr_any;
    serveraddr.sin6_port        = htons(SERVER_PORT);
 
    if (bind(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { [5]
        perror("bind");
        exit(2);
    }
    if (listen(s, SOMAXCONN) < 0) {  [6]
        perror("listen");
        close(s);
        exit(3);
    }
    while (1) {
        int new_s;
        clientaddrlen = sizeof(clientaddr);
        bzero((char *)&clientaddr, clientaddrlen); [7]
        new_s = accept(s, (struct sockaddr*)&clientaddr, &clientaddrlen); [8]
 
        if (new_s < 0) {
            perror("accept");
            continue;
        }
        dcount = recv(new_s, databuf, sizeof(databuf), 0); [9]
        if (dcount < 0) {
            perror("recv");
            close(new_s);
            continue;
        }
        databuf[dcount] = '\0';
 
        printf("Request received from");
        ni = getnameinfo((struct sockaddr *)&clientaddr, [10]
            clientaddrlen, node, sizeof(node), NULL, 0, NI_NAMEREQD);
        if (ni == 0)
            printf(" %s", node);
        ni = getnameinfo((struct sockaddr *)&clientaddr, [11]
            clientaddrlen, addrbuf, sizeof(addrbuf), port, sizeof(port),
            NI_NUMERICHOST|NI_NUMERICSERV);
        if (ni == 0)
            printf(" (%s) port %d", addrbuf, port);
        printf(" \"%s\"\n", port, databuf);
        if (send(new_s, response, strlen(response), 0) < 0) { [12]
            perror("send");
            close(new_s);
            continue;
        }
        close(new_s);
    }
    close(s);
}
 
 

  1. Declares the sockaddr_in6 structure named serveraddr. The use of this type of structure is dictated by the communication domain of the socket (AF_INET6), which implies communication using the IPv6 protocol. [Return to example]

  2. Declares a sockaddr_storage structure named clientaddr. The use of this type of structure enables your program to be protocol independent. [Return to example]

  3. Creates an AF_INET6 socket. The socket type SOCK_STREAM is specified for TCP or connection-oriented communication. [Return to example]

  4. Clears the server address and sets up the server variables. [Return to example]

  5. Binds the server's address to the AF_INET socket. [Return to example]

  6. Listens on the socket for a connection. The server will queue up to SOMAXCONN pending connections while it finishes processing the previous accept call. See sys_attrs_socket(5) for more information on the socket subsystem kernel attributes. [Return to example]

  7. Clears the client address. [Return to example]

  8. Accepts a connection on this socket. The accept call places the client's address in the sockaddr_storage structure named clientaddr. [Return to example]

  9. Receives data from the client. [Return to example]

  10. Obtains the client's name with a call to getnameinfo using the address in the sockaddr_storage structure named clientaddr. The NI_NAMEREQD flag directs the routine to return a host name for the given address. [Return to example]

  11. Obtains the client's numeric address value and port nnumber with a call to getnameinfo using the address in the sockaddr_storage structure named clientaddr. The NI_NUMERICHOST and NI_NUMERICSERV flags direct the routine to return a values for the given address and the port number. [Return to example]

  12. Sends a response to the client. [Return to example]

C.3    Sample Program Output

This section contains sample output from the server and client programs. The server program makes and receives all requests on an AF_INET6 socket using sockaddr_in6. For requests received over IPv4, sockaddr_in6 contains an IPv4-mapped IPv6 address.

The following example shows the client program running on node hostb6 and sending a request to node hosta6. The program uses an AF_INET6 socket. The hosta6 node has the IPv6 address 3ffe:1200::a00:2bff:fe97:7be0 in the Domain Name System (DNS).

user2@hostb6> ./client hosta6
Response received from hosta6.ipv6.corp.example (3ffe:1200::a00:2bff:fe97:7be0):
 this is the server's response

On the server node, the following example shows the server program invocation and the request received from the client node hostb6:

user1@hosta6> ./server
Request received from hostb6.ipv6.corp.example (3ffe:1200::a00:2bff:fe2d:02b2
 port 7739 "this is the client's request"
 
 

The following example shows the client program running on node hostb and sending a request to node hosta. The program uses an AF_INET6 socket. The hosta node has the IPv4 address 10.10.10.13 in the DNS.

user2@hostb> ./client hosta
Response received from hosta.corp.example (::ffff:10.10.10.13): this is the
 server's response

On the server node, the following example shows the server program invocation and the request received from the client node hostb:

user1@hosta6> ./server
Request received from hostb.corp.example (::ffff:10.10.10.251) port 7739
 "this is the client's request"
 
 

The following example shows the client program running on node hostc and sending a request to node hosta. The program was built and run on an IPv4-only system using an AF_INET socket.

user3@hostc> ./client hosta
Response received from hosta.corp.example (10.10.10.13): this is the
 server's response

On the server node, the following example shows the server program invocation and the request received from the client node hostc:

user1@hosta6> ./server
Request received from hostc.corp.example (::ffff:10.10.10.63) port 7739
 "this is the client's request"