HP OpenVMS Systems Documentation

Content starts here

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