# Compaq TCP/IP Services for OpenVMS
Sockets API and System Services Programming

Previous | Contents | Index

## E.1.3 TCP Server Accepting a Connection from the Auxiliary Server

Example E-3 shows how a typical TCP/IP IPv4 server uses the BSD Version 4.x Sockets API to handle network I/O operations, and how the server accepts connections from the auxiliary server.

Example E-3 TCP Auxiliary Server (Sockets API)

    #pragma module  tcpip$tcp_server_sock_auxs              \
                    "V5.1-00"

    /*
     * Copyright 2000 Compaq Computer Corporation
     *
     * COMPAQ Registered in U.S. Patent and Trademark Office.
     *
     * Confidential computer software.  Valid license from  Compaq
     * or  authorized sublicensor required for possession, use  or
     * copying.  Consistent with FAR 12.211 and 12.212, Commercial
     * Computer Software,   Computer Software Documentation,   and
     * Technical Data for Commercial Items  are  licensed  to  the
     * U.S. Government under vendor's standard commercial license.
     *
     * ++
     * FACILITY:
     *
     *    EXAMPLES
     *
     * ABSTRACT:
     *
     *    This is an example of a TCP/IP IPv4 server using  4.x BSD
     *    socket Application Programming Interface (API) to  handle
     *    network I/O operations.  In addition,  it  shows  how  to
     *    accept connections from the auxiliary server.
     *
     *    Refer to 'Build, Configuration, and Run Instructions' for
     *    details on how to build, configure, and run this program.
     *
     * ENVIRONMENT:
     *
     *    OpenVMS Alpha/VAX V7.1
     *    TCP/IP Services V5.0 or higher
     *
     * AUTHOR:
     *
     *    TCPIP Development Group,  CREATION DATE: 23-May-1989
     *
     * --
     */

            /* Build, Configuration, and Run Instructions */

    /*
     *  BUILD INSTRUCTIONS:
     *
     *    To build this example program use commands of the form,
     *
     *    using the DEC "C" compiler:
     *
     *      $ cc/prefix=all TCPIP$TCP_SERVER_SOCK_AUXS.C
     *      $ link TCPIP$TCP_SERVER_SOCK_AUXS
     *
     *    using the DEC "C++" compiler:
     *
     *      $ cxx/prefix=all/define=VMS TCPIP$TCP_SERVER_SOCK_AUXS.C
     *      $ link TCPIP$TCP_SERVER_SOCK_AUXS
     *
     *
     * CONFIGURATION INSTRUCTIONS:
     *
     *    To configure this example program:
     *
     *    1) Create a service run command procedure, named HELLO_RUN.COM, that
     *       contains the following lines:
     *
     *       $ define sys$output ddcu:[directory]hello_service.log
     *       $ define sys$error  ddcu:[directory]hello_service.log
     *       $ run ddcu:[directory]tcpip$tcp_server_sock_auxs.exe
     *
     *       where: ddcu:[directory] is the device and directory of where the
     *              hello service run command procedure file resides
     *
     *    2) Create a service database entry for the hello service as shown below:
     *
     *       $ tcpip set service hello -
     *       _$ /port=12345 -
     *       _$ /protocol=tcp -
     *       _$ /user=vms_user_account -
     *       _$ /process_name=hello_world -
     *       _$ /file=ddcu:[directory]hello_run.com
     *
     *    3) Enable the hello service to run as shown below:
     *
     *       $ tcpip enable service hello
     *
     *
     * RUN INSTRUCTIONS:
     *
     *    To run this example program:
     *
     *    1) Start the client program, entering the server host as shown below:
     *
     *       $ run tcpip$tcp_client_sock
     *       Enter remote host:
     *
     *       Note: You can specify a server host by using either an IPv4
     *             address in dotted-decimal notation (e.g. 16.20.10.56)
     *             or a host domain name (e.g. serverhost.compaq.com).
     *
     *    2) The auxiliary server receives the hello service request, creates a
     *       process, then executes the commands in hello_run.com to  run  this
     *       server program.  This server program then logs  client  connection
     *       information and client data to the service log before replying  to
     *       the client host with a message of "Hello, world!".
     *
     */

    /*
     * INCLUDE FILES:
     */

    #include <in.h>                     /* define internet related constants,   */
                                        /* functions, and structures            */
    #include <inet.h>                   /* define network address 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 <tcpip$inetdef.h>          /* define tcp/ip network constants,     */
                                        /* structures, and functions            */

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

    /*
     * FORWARD REFERENCES:
     */

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

    /*
     * FUNCTIONAL DESCRIPTION:
     *
     *    This is the server's main-line code. It handles all the tasks of the
     *    server including:  socket creation,  writing client connection data,
     *    and terminating client connections.
     *
     *    This example program implements a typical TCP IPv4 server using  the
     *    BSD socket  API  to  handle network i/o operations.  In addition, it
     *    uses the auxiliary server to accept client connections.
     *
     *      1) To create a socket:
     *
     *         socket()
     *
     *      2) To transfer data:
     *
     *         send()
     *
     *      3) To close a socket:
     *
     *         close()
     *
     *    This function is invoked by the DCL "RUN" command (see below);  the
     *    function's  completion  status is interpreted by DCL and if needed,
     *    an error message is displayed.
     *
     * SYNOPSIS:
     *
     *    int main( void )
     *
     * FORMAL PARAMETERS:
     *
     *    ** None **
     *
     * IMPLICIT INPUTS:
     *
     *    ** None **
     *
     * IMPLICIT OUTPUTS:
     *
     *    ** None **
     *
     * FUNCTION VALUE:
     *
     *    completion status
     *
     * SIDE EFFECTS:
     *
     *    ** None **
     *
     */

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

        unsigned int client_addrlen;        /* returned length of client socket */
                                            /* address structure                */
        struct sockaddr_in client_addr;     /* client socket address structure  */

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

        /*
         * init client's socket address structure
         */

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

        /*
         * create socket
         */

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

        /*
         * log this client connection
         */

        client_addrlen = sizeof(client_addr);

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

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

        /*
         * connection established with a client;
         * now attempt to write on this connection
         */

        if ( send(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  */

        /*
         * close socket
         */

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

        exit( EXIT_SUCCESS );
    }

# E.2 TCP Client/Server Examples (System Services)

This section contains the following examples:

- A TCP/IP IPv4 client using $QIO system services to handle network I/O operations.
- A TCP/IP IPv4 server using $QIO system services to handle network I/O operations.
- A TCP/IP IPv4 server using $QIO system services to handle network I/O operations and how the server accepts connections from the auxiliary server.

## E.2.1 TCP Client

Example E-4 shows how a typical TCP IPv4 client uses $QIO system services to handle the tasks of creating a socket, initiating server connections, reading service connection data, and then terminating the server connections.

Example E-4 TCP Client (System Services)

    #pragma module  tcpip$tcp_client_qio                    \
                    "V5.1-00"
    /*
     * Copyright 2000 Compaq Computer Corporation
     *
     * COMPAQ Registered in U.S. Patent and Trademark Office.
     *
     * Confidential computer software.  Valid license from  Compaq
     * or  authorized sublicensor required for possession, use  or
     * copying.  Consistent with FAR 12.211 and 12.212, Commercial
     * Computer Software,   Computer Software Documentation,   and
     * Technical Data for Commercial Items  are  licensed  to  the
     * U.S. Government under vendor's standard commercial license.
     *
     * ++
     * FACILITY:
     *
     *    EXAMPLES
     *
     * ABSTRACT:
     *
     *    This is an example of a TCP/IP IPv4 client using  OpenVMS
     *    QIO system services to handle network I/O operations.
     *
     *    Refer to 'Build, Configuration, and Run Instructions' for
     *    details on how to build, configure, and run this program.
     *
     * ENVIRONMENT:
     *
     *    OpenVMS Alpha/VAX V7.1
     *    TCP/IP Services V5.0 or higher
     *
     * AUTHOR:
     *
     *    TCPIP Development Group,  CREATION DATE: 23-May-1989
     *
     * --
     */
            /* Build, Configuration, and Run Instructions */

    /*
     * BUILD INSTRUCTIONS:
     *
     *    To build this example program use commands of the form,
     *
     *    using the DEC "C" compiler:
     *
     *      $ cc/prefix=all TCPIP$TCP_CLIENT_QIO.C
     *      $ link TCPIP$TCP_CLIENT_QIO
     *
     *    using the DEC "C++" compiler:
     *
     *      $ cxx/prefix=all/define=VMS TCPIP$TCP_CLIENT_QIO.C
     *      $ link TCPIP$TCP_CLIENT_QIO
     *
     *
     * CONFIGURATION INSTRUCTIONS:
     *
     *    No special configuration required.
     *
     *
     * RUN INSTRUCTIONS:
     *
     *    To run this example program:
     *
     *    1) Start the client's server program as shown below:
     *
     *       $ run tcpip$tcp_server_qio
     *       Waiting for a client connection on port: m
     *
     *    2) After the server program blocks, start this client program,
     *       entering the server host as shown below:
     *
     *       $ run tcpip$tcp_client_qio
     *       Enter remote host:
     *
     *       Note: You can specify a server host by using either an IPv4
     *             address in dotted-decimal notation (e.g. 16.20.10.56)
     *             or a host domain name (e.g. serverhost.compaq.com).
     *
     *    3) The client program then displays server connection information
     *       and server data as show below:
     *
     *       Initiated connection to host: a.b.c.d, port: n
     *       Data received: Hello, world!
     *
     *    You can enter "ctrl/z" at any user prompt to terminate program
     *    execution.
     *
     */

    /*
     * INCLUDE FILES:
     */

    #include <descrip.h>                /* define OpenVMS descriptors           */

    #include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */

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

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

    #include <ssdef.h>                  /* define system service status codes   */
    #include <starlet.h>                /* define system service calls          */
    #include <stdio.h>                  /* define standard i/o functions        */
    #include <stdlib.h>                 /* define standard library functions    */
    #include <string.h>                 /* define string handling functions     */
    #include <stsdef.h>                 /* define condition value fields        */

    #include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */
                                        /* structures, and functions            */

    /*
     * NAMED CONSTANTS:
     */

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

    /*
     * STRUCTURE DEFINITIONS:
     */

    struct iosb
        {                                   /* i/o status block                 */
        unsigned short status;              /* i/o completion status            */
        unsigned short bytcnt;              /* bytes transferred if read/write  */
        void *details;                      /* address of buffer or parameter   */
        };

    struct itemlst_2
        {                                   /* item-list 2 descriptor/element   */
        unsigned short length;              /* length                           */
        unsigned short type;                /* parameter type                   */
        void *address;                      /* address of item list             */
        };

    struct sockchar
        {                                   /* socket characteristics buffer    */
        unsigned short prot;                /* protocol                         */
        unsigned char type;                 /* type                             */
        unsigned char af;                   /* address format                   */
        };

    /*
     * FORWARD REFERENCES:
     */

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

    /*
     * FUNCTIONAL DESCRIPTION:
     *
     *    This is the client's main-line code. It handles all the tasks of the
     *    client including:  socket creation,  initiating server  connections,
     *    reading server connection data, and terminating server connections.
     *
     *    This example program implements a typical TCP IPv4 client using  QIO
     *    system services to handle network i/o operations as shown below:
     *
     *      1) To create a socket:
     *
     *         sys$assign() and sys$qiow(IO$_SETMODE)
     *
     *      2) To initiate a connection:
     *
     *         sys$qiow(IO$_ACCESS)
     *
     *      3) To transfer data:
     *
     *         sys$qiow(IO$_READVBLK)
     *
     *      4) To shutdown a socket:
     *
     *         sys$qiow(IO$_DEACCESS|IO$M_SHUTDOWN)
     *
     *      5) To close and delete a socket:
     *
     *         sys$qiow(IO$_DEACCESS) and sys$dassgn()
     *
     *    This function is invoked by the DCL "RUN" command (see below);  the
     *    function's  completion  status is interpreted by DCL and if needed,
     *    an error message is displayed.
     *
     * SYNOPSIS:
     *
     *    int main( void )
     *
     * FORMAL PARAMETERS:
     *
     *    ** None **
     *
     * IMPLICIT INPUTS:
     *
     *    ** None **
     *
     * IMPLICIT OUTPUTS:
     *
     *    ** None **
     *
     * FUNCTION VALUE:
     *
     *    completion status
     *
     * SIDE EFFECTS:
     *
     *    ** None **
     *
     */

    int
    main( void )
    {
        struct iosb iosb;                   /* i/o status block                 */

        unsigned int status;                /* system service return status     */

        char buf[512];                      /* client data buffer               */
        int  buflen = sizeof( buf );        /* length of client data buffer     */

        unsigned short conn_channel;        /* connect inet device i/o channel  */
        struct sockchar conn_sockchar;      /* connect socket char buffer       */

        struct sockaddr_in serv_addr;       /* server socket address structure  */
        struct itemlst_2 serv_itemlst;      /* server item-list 2 descriptor    */

        $DESCRIPTOR( inet_device,           /* string descriptor with logical   */
                     "TCPIP$DEVICE" );      /* name of internet pseudodevice    */

        /*
         * init connection socket characteristics buffer
         */

        conn_sockchar.prot = TCPIP$C_TCP;
        conn_sockchar.type = TCPIP$C_STREAM;
        conn_sockchar.af   = TCPIP$C_AF_INET;

        /*
         * init server's item-list descriptor
         */

        memset( &serv_itemlst, 0, sizeof(serv_itemlst) );
        serv_itemlst.length  = sizeof( serv_addr );
        serv_itemlst.address = &serv_addr;

        /*
         * init server's socket address structure
         */

        memset( &serv_addr, 0, sizeof(serv_addr) );
        serv_addr.sin_family = TCPIP$C_AF_INET;
        serv_addr.sin_port   = htons( SERV_PORTNUM );
        get_serv_addr( &serv_addr.sin_addr );

        /*
         * assign device socket
         */

        status = sys$assign( &inet_device,      /* device name                  */
                             &conn_channel,     /* i/o channel                  */
                             0,                 /* access mode                  */
                             0                  /* not used                     */
                           );

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to assign i/o channel to TCPIP device\n" );
            exit( status );
            }

        /*
         * create connection socket
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           conn_channel,        /* i/o channel                  */
                           IO$_SETMODE,         /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           &conn_sockchar,      /* p1 - socket char buffer      */
                           0,                   /* p2                           */
                           0,                   /* p3                           */
                           0,                   /* p4                           */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to create socket\n" );
            exit( status );
            }

        /*
         * connect to specified host and port number
         */

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

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           conn_channel,        /* i/o channel                  */
                           IO$_ACCESS,          /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           &serv_itemlst,       /* p3 - remote socket name      */
                           0,                   /* p4                           */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to connect to server\n" );
            exit( status );
            }

        /*
         * connection established with a server;
         * now attempt to read on this connection
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           conn_channel,        /* i/o channel                  */
                           IO$_READVBLK,        /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           buf,                 /* p1 - buffer address          */
                           buflen,              /* p2 - buffer length           */
                           0,                   /* p3                           */
                           0,                   /* p4                           */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to read data from server connection\n" );
            exit( status );
            }

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

        /*
         * shutdown connection socket
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           conn_channel,        /* i/o channel                  */
                           IO$_DEACCESS|IO$M_SHUTDOWN,
                                                /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           0,                   /* p3                           */
                           TCPIP$C_DSC_ALL,     /* p4 - discard all packets     */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to shutdown server connection\n" );
            exit( status );
            }

        /*
         * close connection socket
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           conn_channel,        /* i/o channel                  */
                           IO$_DEACCESS,        /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           0,                   /* p3                           */
                           0,                   /* p4                           */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to close socket\n" );
            exit( status );
            }

        /*
         * deassign device socket
         */

        status = sys$dassgn( conn_channel );

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to deassign i/o channel to TCPIP device\n" );
            exit( status );
            }

        exit( EXIT_SUCCESS );
    }
            /* Get Server Host Address */

    /*
     * FUNCTIONAL DESCRIPTION:
     *
     *    This function gets the server host's address from the user and then
     *    stores it in the server's socket address structure.  Note that  the
     *    user can specify a server host by using either an IPv4  address  in
     *    dotted-decimal notation (e.g. 16.20.10.126) or a host  domain  name
     *    (e.g. serverhost.compaq.com).
     *
     *    Enter "ctrl/z" to terminate program execution.
     *
     * SYNOPSIS:
     *
     *    void get_serv_addr( void *addrptr )
     *
     * FORMAL PARAMETERS:
     *
     *    addrptr  -  pointer to socket address structure's 'sin_addr' field
     *                to store the specified network address
     *
     * IMPLICIT INPUTS:
     *
     *    ** None **
     *
     * IMPLICIT OUTPUTS:
     *
     *    ** None **
     *
     * FUNCTION VALUE:
     *
     *    ** None **
     *
     * SIDE EFFECTS:
     *
     *    Program execution is terminated if unable to read user's input.
     *
     */

    void
    get_serv_addr( void *addrptr )
    {
        char buf[BUFSZ];
        struct in_addr val;
        struct hostent *host;

        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)) )
                {
                memcpy( addrptr, host->h_addr, sizeof(struct in_addr) );
                break;
                }
            }
    }

Previous | Next | Contents | Index