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


Previous Contents Index

E.2.2 TCP Server

Example E-5 shows how a typical TCP IPv4 server uses $QIO system services to handle the tasks of creating a socket, accepting or rejecting client connections, writing client connection data, and then terminating client connections.

Example E-5 TCP Server (System Services)

 
#pragma module  tcpip$tcp_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 TCP/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$TCP_SERVER_QIO.C 
 *      $ link TCPIP$TCP_SERVER_QIO 
 *    
 *    using the DEC "C++" compiler: 
 *    
 *      $ cxx/prefix=all/define=VMS TCPIP$TCP_SERVER_QIO.C 
 *      $ link TCPIP$TCP_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$tcp_server_qio 
 *       Waiting for a client connection on port: m 
 * 
 *    2) After the server program blocks, start the 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 server program then displays client connection information 
 *       and client data as shown below: 
 * 
 *       Accepted connection from host: a.b.c.d, port: n 
 *       Data sent: 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_BACKLOG    1               /* server backlog                   */ 
#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 );                      /* 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, accepting and/or rejecting client 
 *    connections, writing client connection data,  and terminating client 
 *    connections. 
 * 
 *    This example program implements a typical TCP 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 accept a connection request: 
 * 
 *         sys$qiow(IO$_ACCESS|IO$M_ACCEPT) 
 * 
 *      4) To transfer data: 
 * 
 *         sys$qiow(IO$_WRITEVBLK) 
 * 
 *      5) To shutdown a socket: 
 * 
 *         sys$qiow(IO$_DEACCESS|IO$M_SHUTDOWN) 
 * 
 *      6) 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           */ 
 
    struct iosb iosb;                   /* i/o status block                 */ 
 
    unsigned int status;                /* system service return status     */ 
 
    unsigned short conn_channel;        /* connect inet device i/o channel  */ 
    unsigned short listen_channel;      /* listen inet device i/o channel   */ 
 
    struct sockchar listen_sockchar;    /* listen 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    */ 
 
    char buf[] = "Hello, World!";       /* server data buffer               */ 
    int  buflen = sizeof( buf );        /* length of server data buffer     */ 
 
    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */ 
                 "TCPIP$DEVICE" );      /* name of internet pseudodevice    */ 
 
    /* 
     * init listen socket characteristics buffer 
     */ 
 
    listen_sockchar.prot = TCPIP$C_TCP; 
    listen_sockchar.type = TCPIP$C_STREAM; 
    listen_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 sockets 
     */ 
 
    status = sys$assign( &inet_device,      /* device name                  */ 
                         &listen_channel,   /* i/o channel                  */ 
                         0,                 /* access mode                  */ 
                         0                  /* not used                     */ 
                       ); 
 
    if ( (status & STS$M_SUCCESS) ) 
        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(s) to TCPIP device\n" ); 
        exit( status ); 
        } 
 
    /* 
     * create a listen socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       listen_channel,      /* i/o channel                  */ 
                       IO$_SETMODE,         /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       &listen_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 
     * listen socket; set socket as a passive socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       listen_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       */ 
                       SERV_BACKLOG,        /* p4 - connection backlog      */ 
                       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 ); 
        } 
 
    /* 
     * accept a connection from a client 
     */ 
 
    printf( "Waiting for a client connection on port: %d\n", 
            ntohs(serv_addr.sin_port) 
          ); 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       listen_channel,      /* i/o channel                  */ 
                       IO$_ACCESS|IO$M_ACCEPT, 
                                            /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       0,                   /* p1                           */ 
                       0,                   /* p2                           */ 
                       &client_itemlst,     /* p3 - remote socket name      */ 
                       &conn_channel,       /* p4 - i/o channel for new     */ 
                                            /*      connection              */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to accept client connection\n" ); 
        exit( status ); 
        } 
 
    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 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       conn_channel,        /* i/o channel                  */ 
                       IO$_WRITEVBLK,       /* 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 write data to client connection\n" ); 
        exit( status ); 
        } 
 
    printf( "Data sent: %s\n", buf );       /* output server'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 client 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 ); 
        } 
    /* 
     * close listen socket 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       listen_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 all device sockets 
     */ 
 
    status = sys$dassgn( conn_channel ); 
 
    if ( (status & STS$M_SUCCESS) ) 
        status = sys$dassgn( listen_channel ); 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to deassign i/o channel(s) to TCPIP device\n" ); 
        exit( status ); 
        } 
 
    exit( EXIT_SUCCESS ); 
} 

E.2.3 TCP Server Accepting a Connection from the Auxiliary Server

Example E-6 shows how a typical TCP/IP IPv4 server uses $QIO system services to handle network I/O operations and the server accepts connections from the auxiliary server.

Example E-6 TCP Auxiliary Server (System Services)

 
#pragma module  tcpip$tcp_server_qio_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  OpenVMS 
 *    QIO system services 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_QIO_AUXS.C 
 *      $ link TCPIP$TCP_SERVER_QIO_AUXS 
 *    
 *    using the DEC "C++" compiler: 
 *    
 *      $ cxx/prefix=all/define=VMS TCPIP$TCP_SERVER_QIO_AUXS.C 
 *      $ link TCPIP$TCP_SERVER_QIO_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_qio_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 <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 <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            */ 
 
 
 * 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 );                      /* 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  QIO 
 *    system  services to handle network i/o operations.  In addition,  it 
 *    uses the auxiliary server to accept client connections. 
 * 
 *      1) To create a socket: 
 * 
 *         sys$assign() and sys$qiow(IO$_SETMODE) 
 * 
 *      2) To transfer data: 
 * 
 *         sys$qiow(IO$_WRITEVBLK) 
 * 
 *      3) 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     */ 
 
    unsigned short conn_channel;        /* connect inet device i/o channel  */ 
    struct sockchar conn_sockchar;      /* connect 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    */ 
 
    char buf[] = "Hello, world!";       /* server data buffer               */ 
    int  buflen = sizeof( buf );        /* length of server data buffer     */ 
 
    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */ 
                 "SYS$NET"    );        /* 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_AUXS; 
 
    /* 
     * 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) ); 
 
    /* 
     * 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 ); 
        } 
 
    /* 
     * log this client connection 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       conn_channel,        /* i/o channel                  */ 
                       IO$_SENSEMODE,       /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       0,                   /* p1                           */ 
                       0,                   /* p2                           */ 
                       0,                   /* p3                           */ 
                       &client_itemlst,     /* p4 - peer socket name        */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to accept client connection\n" ); 
        exit( status ); 
        } 
 
    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 
     */ 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       conn_channel,        /* i/o channel                  */ 
                       IO$_WRITEVBLK,       /* 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 write data to client connection\n" ); 
        exit( status ); 
        } 
    printf( "Data sent: %s\n", buf );       /* output server's data buffer  */ 
    /* 
     * 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                           */ 
                       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 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 ); 
} 


Previous Next Contents Index