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

Previous | Contents | Index

## E.4.2 UDP Server

Example E-10 shows how a typical UDP IPv4 server uses $QIO system services to handle the tasks of creating a socket, binding a socket to the server's internet address and port, and reading client data.

Example E-10 UDP Server (System Services)

    #pragma module  tcpip$udp_server_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 UDP/IP IPv4 server 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$UDP_SERVER_QIO.C
     *      $ link TCPIP$UDP_SERVER_QIO
     *
     *    using the DEC "C++" compiler:
     *
     *      $ cxx/prefix=all/define=VMS TCPIP$UDP_SERVER_QIO.C
     *      $ link TCPIP$UDP_SERVER_QIO
     *
     *
     * CONFIGURATION INSTRUCTIONS:
     *
     *    No special configuration required.
     *
     *
     * RUN INSTRUCTIONS:
     *
     *    To run this example program:
     *
     *    1) Start this server program as shown below:
     *
     *       $ run tcpip$udp_server_qio
     *       Waiting for a client datagram on port: m
     *
     *    2) After the server program blocks, start the client program,
     *       entering the server host as shown below:
     *
     *       $ run tcpip$udp_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 server program then displays client address information
     *       and client data as show below:
     *
     *       Received a datagram from 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 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 itemlst_3
        {                                   /* item-list 3 descriptor/element   */
        unsigned short length;              /* length                           */
        unsigned short type;                /* parameter type                   */
        void *address;                      /* address of item list             */
        unsigned int *retlen;               /* address of returned length       */
        };

    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                      */
            /* Server Main */

    /*
     * FUNCTIONAL DESCRIPTION:
     *
     *    This is the server's main-line code. It handles all the tasks of the
     *    server including: socket creation, binding a socket to the  server's
     *    internet address and port, and reading client data.
     *
     *    This example program implements a typical UDP IPv4 server using  QIO
     *    system services to handle network i/o operations as shown below:
     *
     *      1) To create a socket and set REUSEADDR option:
     *
     *         sys$assign() and sys$qiow(IO$_SETMODE)
     *
     *      2) To bind internet address and port number to a socket:
     *
     *         sys$qiow(IO$_SETMODE)
     *
     *      3) To transfer data:
     *
     *         sys$qiow(IO$_READVBLK)
     *
     *      4) 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 )
    {
        int one = 1;                        /* reuseaddr option value           */

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

        struct iosb iosb;                   /* i/o status block                 */

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

        unsigned short inet_channel;        /* inet device i/o channel          */
        struct sockchar udp_sockchar;       /* socket char buffer               */

        unsigned int client_retlen;         /* returned length of client socket */
                                            /* address structure                */
        struct sockaddr_in client_addr;     /* client socket address structure  */
        struct itemlst_3 client_itemlst;    /* client item-list 3 descriptor    */

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

        struct itemlst_2 sockopt_itemlst;   /* sockopt item-list 2 descriptor   */
        struct itemlst_2 reuseaddr_itemlst; /* reuseaddr item-list 2 element    */

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

        /*
         * init udp socket characteristics buffer
         */

        udp_sockchar.prot = TCPIP$C_UDP;
        udp_sockchar.type = TCPIP$C_DGRAM;
        udp_sockchar.af   = TCPIP$C_AF_INET;

        /*
         * init reuseaddr's item-list element
         */

        reuseaddr_itemlst.length  = sizeof( one );
        reuseaddr_itemlst.type    = TCPIP$C_REUSEADDR;
        reuseaddr_itemlst.address = &one;

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

        sockopt_itemlst.length  = sizeof( reuseaddr_itemlst );
        sockopt_itemlst.type    = TCPIP$C_SOCKOPT;
        sockopt_itemlst.address = &reuseaddr_itemlst;

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

        memset( &client_itemlst, 0, sizeof(client_itemlst) );
        client_itemlst.length  = sizeof( client_addr );
        client_itemlst.address = &client_addr;
        client_itemlst.retlen  = &client_retlen;

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

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

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

        serv_itemlst.length  = sizeof( serv_addr );
        serv_itemlst.type    = TCPIP$C_SOCK_NAME;
        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 );
        serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;

        /*
         * assign device socket
         */

        status = sys$assign( &inet_device,      /* device name                  */
                             &inet_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 udp socket
         */

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

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

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

        /*
         * bind server's internet address and port number to socket
         */

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

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

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

        /*
         * read datagram from client
         */

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

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           inet_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           */
                           &client_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 read datagram from client\n" );
            exit( status );
            }

        printf( "Received a datagram from host: %s, port: %d\n",
                inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)
              );
        printf( "Data received: %s\n", buf );   /* output client's data         */

        /*
         * close udp socket
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           inet_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( inet_channel );

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

        exit( EXIT_SUCCESS );
    }

Index | Contents