HP OpenVMS Systems Documentation

Content starts here

HP TCP/IP Services for OpenVMS
Sockets API and System Services Programming


Previous Contents Index

E.5.5 Changing Socket Options

If your application uses IPv4 IP-level socket options, change them to the corresponding IPv6 options.

E.6 Sample Client/Server Programs

This section contains sample client and server programs that demonstrate the differences between IPv4 and IPv6 coding conventions:

To build the examples, use the following commands:


$ CC/DEFINE=(_SOCKADDR_LEN)/INCLUDE=TCPIP$EXAMPLES: client.c
$ LINK client, TCPIP$LIBRARY:TCPIP$LIB/LIBRARY

$ CC/DEFINE=(_SOCKADDR_LEN)/INCLUDE=TCPIP$EXAMPLES: server.c
$ LINK server, TCPIP$LIBRARY:TCPIP$LIB/LIBRARY

E.6.1 Programs Using AF_INET Sockets

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

E.6.1.1 Client Program

The following is 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.


#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */

#include <netdb.h>                  /* define network database library info */

#include <socket.h>                 /* define BSD 4.x socket api            */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */
#include <string.h>                 /* define string handling functions     */

#include <unixio.h>                 /* define unix i/o                      */

#define BUFSZ           1024        /* user input buffer size               */
#define SERV_PORTNUM    12345       /* server port number                   */

int  main( void );                  /* client main                          */
void get_serv_addr( void * );(1)     /* get server host address              */

int
main( void )
{
    int sockfd;                      /* connection socket descriptor        */

    char buf[512];                   /* client data buffer                  */

    struct sockaddr_in serv_addr;(2)  /* server socket address structure     */

    memset( &serv_addr, 0, sizeof(serv_addr) );(3)
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port   = htons( SERV_PORTNUM );
    get_serv_addr( &serv_addr.sin_addr );(4)

    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )(5)
        {
        perror( "Failed to create socket" );
        exit( EXIT_FAILURE );
        }

    printf( "Initiated connection to host: %s, port: %d\n",
          inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port)(6)
          );

    if ( connect(sockfd,
                (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )(7)
        {
        perror( "Failed to connect to server" );
        exit( EXIT_FAILURE );
        }

    if ( recv(sockfd, buf, sizeof(buf), 0) < 0 )
        {
        perror( "Failed to read data from server connection" );
        exit( EXIT_FAILURE );
        }

    printf( "Data received: %s\n", buf );  /* output client's data buffer  */

    if ( shutdown(sockfd, 2) < 0 )
        {
        perror( "Failed to shutdown server connection" );
        exit( EXIT_FAILURE );
        }

    if ( close(sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    exit( EXIT_SUCCESS );
}

void
get_serv_addr( void *addrptr )(8)
{
    char buf[BUFSZ];        /* input data buffer              */
    struct in_addr val;     /* remote host address structure  */
    struct hostent *host;   /* remote host hostent structure  */

    while ( TRUE )
        {
        printf( "Enter remote host: " );

        if ( fgets(buf, sizeof(buf), stdin) == NULL )
            {
            printf( "Failed to read User input\n" );
            exit( EXIT_FAILURE );
            }

        buf[strlen(buf)-1] = 0;

        val.s_addr = inet_addr( buf );

        if ( val.s_addr != INADDR_NONE )
            {
            memcpy( addrptr, &val, sizeof(struct in_addr) );
            break;
            }

        if ( (host = gethostbyname(buf)) )(9)
            {
            memcpy( addrptr, host->h_addr, sizeof(struct in_addr) );
            break;
            }
        }
}

This example of a client applications sends a request and receives a response on an AF_INET socket.

  1. Function code prototype for server host address/name translation function.
  2. Declares sockaddr_in structure.
  3. Clears the server sockaddr_in structure and sets values for fields of the structure
  4. Calls get_serv_addr passing a pointer to the socket address structure's sin_addr field.
  5. Creates an AF_INET socket
  6. Calls inet_ntoa to convert the server address to a text string.
  7. Calls connect passing a pointer to the sockaddr_in structure.
  8. Retrieves the server host's address from the user and then stores it in the server's socket address structure. The user can specify a server host by using either an IPv4 address in dotted decimal notation or a host domain name
  9. Calls gethostbyname() to retrieve the server host's address.

E.6.1.2 Server Program

The following is 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.


#include <in.h>                     /* define internet related constants,   */
                                    /* functions, and structures            */
#include <inet.h>                   /* define network address info          */

#include <netdb.h>                  /* define network database library info */

#include <socket.h>                 /* define BSD 4.x socket api            */
#include <stdio.h>                  /* define standard i/o functions        */
#include <stdlib.h>                 /* define standard library functions    */
#include <string.h>                 /* define string handling functions     */

#include <unixio.h>                 /* define unix i/o                      */

#define SERV_BACKLOG    1           /* server backlog                       */
#define SERV_PORTNUM    12345       /* server port number                   */

int  main( void );                  /* server main                          */

int
main( void )
{
    int optval = 1;                 /* SO_REUSEADDR'S option value (on)     */

    int conn_sockfd;                /* connection socket descriptor         */
    int listen_sockfd;              /* listen socket descriptor             */

    unsigned int client_addrlen;    /* returned length of client socket     */
                                    /* address structure                    */
    struct sockaddr_in client_addr;(1) /* client socket address structure    */
    struct sockaddr_in serv_addr;   /* server socket address structure      */

    struct hostent *host;(2)         /* host name structure                  */

    char buf[] = "Hello, world!";   /* server data buffer                   */

    memset( &client_addr, 0, sizeof(client_addr) );

    memset( &serv_addr, 0, sizeof(serv_addr) );(3)
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_port        = htons( SERV_PORTNUM );
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )(4)
        {
        perror( "Failed to create socket" );
        exit( EXIT_FAILURE );
        }

    if ( setsockopt(listen_sockfd,
      SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0 )
        {
        perror( "Failed to set socket option" );
        exit( EXIT_FAILURE );
        }

    if ( bind(listen_sockfd,
       (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
        {
        perror( "Failed to bind socket" );
        exit( EXIT_FAILURE );
        }

    if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
        {
        perror( "Failed to set socket passive" );
        exit( EXIT_FAILURE );
        }

    printf( "Waiting for a client connection on port: %d\n",
            ntohs(serv_addr.sin_port)
        );

    client_addrlen = sizeof(client_addr);

    conn_sockfd = accept( listen_sockfd,
                          (struct sockaddr *) &client_addr,
                          &client_addrlen
                        );
    if ( conn_sockfd < 0 )
        {
        perror( "Failed to accept client connection" );
        exit( EXIT_FAILURE );
        }

    host = gethostbyaddr( (char *)&client_addr.sin_addr.s_addr,
                          sizeof(client_addr.sin_addr.s_addr), AF_INET (5)
                          );

    if ( host == NULL )
        {
        perror( "Failed to translate client address\n" );
        exit( EXIT_FAILURE );
        }

    printf( "Accepted connection from host: %s (%s), port: %d\n",
            host->h_name, inet_ntoa(client_addr.sin_addr),
            ntohs(client_addr.sin_port)
          );

    if ( send(conn_sockfd, buf, sizeof(buf), 0) < 0 )
        {
        perror( "Failed to write data to client connection" );
        exit( EXIT_FAILURE );
        }

    printf( "Data sent: %s\n", buf );    /* output server's data buffer  */

    if ( shutdown(conn_sockfd, 2) < 0 )
        {
        perror( "Failed to shutdown client connection" );
        exit( EXIT_FAILURE );
        }

    if ( close(conn_sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    if ( close(listen_sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    exit( EXIT_SUCCESS );
}

This example of a server application sends a request and receives a response on an AF_INET socket.

  1. Declares sockaddr_in structures.
  2. Declares hostent structure.
  3. Clears the server sockaddr_in structure and sets values for fields of the structure.
  4. Creates an AF_INET socket.
  5. Calls gethostbyaddr() to retrieve client name.

E.6.2 Programs Using AF_INET6 Sockets

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

E.6.2.1 Client Program

The following is 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.


#include <in.h>                       /* define internet related constants,   */
                                      /* functions, and structures            */
#include <inet.h>                     /* define network address info          */

#include <netdb.h>                    /* define network database library info */

#include <socket.h>                   /* define BSD 4.x socket api            */
#include <stdio.h>                    /* define standard i/o functions        */
#include <stdlib.h>                   /* define standard library functions    */
#include <string.h>                   /* define string handling functions     */

#include <unixio.h>                   /* define unix i/o                      */


#define BUFSZ           1024          /* user input buffer size               */
#define SERV_PORTNUM    "12345"       /* server port number string            */


int main( void );                     /* client main                          */
void get_serv_addr( struct addrinfo *hints, struct addrinfo **res );(1)
                                      /* get server host address              */

int
main( void )
{
    int sockfd;                       /* connection socket descriptor        */

    char buf[512];                    /* client data buffer                  */

    struct addrinfo hints;            /* input values to direct operation    */
    struct addrinfo *res;(2)           /* linked list of addrinfo structs     */

    memset( &hints, 0, sizeof(hints) );(3)
    hints.ai_family = AF_INET6;
    hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED | AI_CANONNAME;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_socktype = SOCK_STREAM;
    get_serv_addr( &hints, &res );(4)

    if ( (sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0 )(5)
        {
        perror( "Failed to create socket" );
        exit( EXIT_FAILURE );
        }

    printf( "Initiated connection to host: %s, port: %d\n",
            res->ai_canonname,
            htons(((struct sockaddr_in6 *)res->ai_addr)->sin6_port)(6) );

    if ( connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 )(7)
        {
        perror( "Failed to connect to server" );
        exit( EXIT_FAILURE );
        }

    if ( recv(sockfd, buf, sizeof(buf), 0) < 0 )
        {
        perror( "Failed to read data from server connection" );
        exit( EXIT_FAILURE );
        }

    printf( "Data received: %s\n", buf ); /* output client's data buffer   */

    if ( shutdown(sockfd, 2) < 0 )
        {
        perror( "Failed to shutdown server connection" );
        exit( EXIT_FAILURE );
        }

    if ( close(sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    exit( EXIT_SUCCESS );
}

void
get_serv_addr( struct addrinfo *hints, struct addrinfo **res )(8)
{
    int gai_error;                      /* return value of getaddrinfo()  */
    char buf[BUFSZ];                    /* input data buffer              */
    const char *port = SERV_PORTNUM;    /* server port number             */

    while ( TRUE )
        {
        printf( "Enter remote host: " );

        if ( fgets(buf, sizeof(buf), stdin) == NULL )
            {
            printf( "Failed to read User input\n" );
            exit( EXIT_FAILURE );
            }

        buf[strlen(buf)-1] = 0;

        gai_error = getaddrinfo( buf, port, hints, res );(9)
        if ( gai_error )
          printf( "Failed to resolve name or address: %s\n",
                  gai_strerror(gai_error)(10)
                  );
 else
     break;
        }
}

This example of a client application sends a request and receives a response on an AF_INET6 socket.

  1. Function prototype for server host address/name translation function.
  2. Declares addrinfo structures.
  3. Clears the addrinfo structure and sets values for fields of the structure.
  4. Calls get_serv_addr() passing pointers to the input and output addrinfo structures.
  5. Creates an AF_INET6 socket.
  6. Uses values from the output addrinfo structure for host name and port.
  7. Calls connect() using values from the output addrinfo structure.
  8. Retrieves the server host's address from the user and stores it in the addrinfo structure. The user can specify a server host by using any of the following:
    • An IPv4 address in dotted-decimal notation
    • An IPv6 address in hexadecimal
    • An IPv4-mapped IPv6 address in hexadecimal
    • A host domain name
  9. Calls getaddrinfo() to retrieve the server host's name or address.
  10. Calls gai_strerror() to convert one of the EAI_xxx return values to a string describing the error.

E.6.2.2 Server Program

The following is 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.


#include <in.h>                       /* define internet related constants,
                                      /* functions, and structures            */
#include <inet.h>                     /* define network address info          */

#include <netdb.h>                    /* define network database library info */

#include <socket.h>                   /* define BSD 4.x socket api            */
#include <stdio.h>                    /* define standard i/o functions        */
#include <stdlib.h>                   /* define standard library functions    */
#include <string.h>                   /* define string handling functions     */

#include <unixio.h>                   /* define unix i/o                      */

#define SERV_BACKLOG    1             /* server backlog                       */
#define SERV_PORTNUM    12345         /* server port number                   */

int  main( void );                    /* server main                          */

int
main( void )
{
    int optval = 1;                   /* SO_REUSEADDR'S option value (on)     */

    int conn_sockfd;                  /* connection socket descriptor         */
    int listen_sockfd;                /* listen socket descriptor             */
    int gni_error;(1)                  /* return status for getnameinfo()      */

    unsigned int client_addrlen;      /* returned length of client socket     */
                                      /* address structure                    */
    struct sockaddr_in6 client_addr;  /* client socket address structure      */
    struct sockaddr_in6 serv_addr;(2)  /* server socket address structure      */

    char buf[] = "Hello, world!";     /* server data buffer                   */
    char node[NI_MAXHOST];(3)          /* buffer to receive node name          */
    char port[NI_MAXHOST];            /* buffer to receive port number        */
    char addrbuf[INET6_ADDRSTRLEN];   /* buffer to receive host's address     */

    memset( &client_addr, 0, sizeof(client_addr) );

    memset( &serv_addr, 0, sizeof(serv_addr) );(4)
    serv_addr.sin6_family      = AF_INET6;
    serv_addr.sin6_port        = htons( SERV_PORTNUM );
    serv_addr.sin6_addr        = in6addr_any;

    if ( (listen_sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0 )(5)
        {
        perror( "Failed to create socket" );
        exit( EXIT_FAILURE );
        }

    if ( setsockopt(listen_sockfd,
         SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0 )
        {
        perror( "Failed to set socket option" );
        exit( EXIT_FAILURE );
        }

    if ( bind(listen_sockfd,
         (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
        {
        perror( "Failed to bind socket" );
        exit( EXIT_FAILURE );
        }

    if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
        {
        perror( "Failed to set socket passive" );
        exit( EXIT_FAILURE );
        }

    printf( "Waiting for a client connection on port: %d\n",
            ntohs(serv_addr.sin6_port)
          );

    client_addrlen = sizeof(client_addr);

    conn_sockfd = accept( listen_sockfd,
                          (struct sockaddr *) &client_addr,
                          &client_addrlen
                          );
    if ( conn_sockfd < 0 )
        {
        perror( "Failed to accept client connection" );
        exit( EXIT_FAILURE );
        }

    gni_error = getnameinfo( (struct sockaddr *)&client_addr,client_addrlen, (6)
                             node, sizeof(node), NULL, 0, NI_NAMEREQD
                             );
    if ( gni_error )
        {
        printf( "Failed to translate client address: %s\n",
                gai_strerror(gni_error) (7)
              );
        exit( EXIT_FAILURE );
        }

    gni_error = getnameinfo( (struct sockaddr *)&client_addr, client_addrlen,
                             addrbuf, sizeof(addrbuf), port, sizeof(port),
                             NI_NUMERICHOST | NI_NUMERICSERV (8)
                           );
    if ( gni_error )
        {
        printf( "Failed to translate client address and/or port: %s\n",
                gai_strerror(gni_error)
              );
 exit( EXIT_FAILURE );
        }

    printf( "Accepted connection from host: %s (%s), port: %s\n",
            node, addrbuf, port
          );

    if ( send(conn_sockfd, buf, sizeof(buf), 0) < 0 )
        {
        perror( "Failed to write data to client connection" );
        exit( EXIT_FAILURE );
        }

    printf( "Data sent: %s\n", buf );    /* output server's data buffer       */

    if ( shutdown(conn_sockfd, 2) < 0 )
        {
        perror( "Failed to shutdown client connection" );
        exit( EXIT_FAILURE );
        }

    if ( close(conn_sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    if ( close(listen_sockfd) < 0 )
        {
        perror( "Failed to close socket" );
        exit( EXIT_FAILURE );
        }

    exit( EXIT_SUCCESS );
}

This example of a server application sends a request and receives a response on an AF_INET6 socket.

  1. Declares variable for getnameinfo() return value
  2. Declares sockaddr_in6 structures
  3. Declares buffers to receive client's name, port number, and address for calls to getnameinfo() .
  4. Clears the server sockaddr_in6 structure and sets values for fields of the structure.
  5. Creates an AF_INET6 socket.
  6. Calls getnameinfo() to retrieve client name. This is for message displaying purposes only and is not necessary for proper functioning of the server.
  7. Calls gai_strerror() to convert one of the EAI_xxx return values to a string describing the error.
  8. Calls getnameinfo() to retrieve client address and port number. This is for message displaying purposes only and is not necessary for proper functioning of the server.

E.6.3 Sample Program Output

This section contains sample output from the preceding 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.

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


    $ run client.exe
    Enter remote host: hosta6
    Initiated connection to host: hosta6.ipv6.corp.example, port: 12345
    Data received: Hello, world!
    $
    
  2. On the server node, the following example shows the server program invocation and the request received from the client node hostb6 :


    $ run server.exe
    Waiting for a client connection on port: 12345
    Accepted connection from host: hostb6.ipv6.corp.example
    (3ffe:1200::a00:2bff:fe97:7be0), port: 49174
    Data sent: Hello, world!
    $
    
  3. 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 only an IPv4 address in the DNS.


    $ run client.exe
    Enter remote host: hosta
    Initiated connection to host: hosta.corp.example, port 12345
    Data received: Hello, world!
    $
    
  4. On the server node, the following example shows the server program invocation and the request received from the client node hostb :


    $ run server.exe
    Waiting for a client connection on port: 12345
    Accepted connection from host: hostb.corp.example (::ffff:10.10.10.251),
    port: 49175
    Data sent: Hello, world!
    $
    
  5. The following example shows the client program running on node hostb6 and sending a request to node hosta6 using its link-local address fe80::a00:2bff:fe97:7be0. The program uses an AF_INET6 socket.


    $ run client.exe
    Enter remote host: fe80::a00:2bff:fe97:7be0
    Initiated connection to host: fe80::a00:2bff:fe97:7be0, port: 12345
    Data received: Hello, world!
    $
    
  6. On the server node, the following example shows the server program invocation and the request received from the client node hostb6 .


    $ run server.exe
    Waiting for a client connection on port: 12345
    Accepted connection from host: hosta6.ipv6.corp.example%WE0
    (fe80::a00:2bff:fe97:7be0%WE0), port: 49177
    Data sent: Hello, world!
    $
    


Index Contents