DIGITAL TCP/IP Services for OpenVMS
System Services and C Socket Programming


Previous Contents Index


Appendix A
Online Program Examples

Table A-1 lists the sample programs printed in this appendix. See Table 1-1 and Table 1-2 for a complete list of all the sample programs provided online in TCPIP$EXAMPLES.

Table A-1 Location of Online Program Examples --- TCPIP$EXAMPLES:
File See...
TCPIP$TCP_SERVER_QIO.C Section A.1
TCPIP$UDP_SERVER_IPC.C Section A.2
TCPIP$TCP_SERVER_IPC.C Section A.3
TCPIP$TCP_SERVER_IPC_AUXS.C Section A.4
TCPIP$TCP_CLIENT_IPC.C Section A.5

A.1 TCP/IP Server Using QIO Calls

Example A-1 shows a TCP/IP server using QIO calls. You can access this file online in TCPIP$EXAMPLES:TCPIP$TCP_SERVER_QIO.C.

Depending on your compiler, you can compile and link this program in any of the following ways:

Example A-1 TCP/IP Server Using QIO Calls

 
#include <descrip.h>        /* OpenVMS descriptor information */ 
#include <errno.h>          /* UNIX style error codes for I/O routines */ 
#include <in.h>             /* Internet system constants and structures */ 
#include <inet.h>           /* Network address information */ 
#include <iodef.h>          /* I/O function code definitions */ 
#include <lib$routines.h>   /* LIB$ RTL-routine signatures */ 
#include <lib$routines.h>   /* LIB$ RTL-routine signatures */ 
#include <netdb.h>          /* Network database library information */ 
#include <signal.h>         /* UNIX style signal value definitions */ 
#include <socket.h>         /* TCP/IP socket definitions */ 
#include <ssdef.h>          /* SS$_<xyz> system service return status codes */ 
#include <starlet.h>        /* System service calls */ 
#include <stdio.h>          /* UNIX 'standard I/O' definitions   */ 
#include <stdlib.h>         /* General utilities */ 
#include <string.h>         /* String handling function definitions */ 
#include <tcpip$inetdef.h>    /* Network definitions */ 
 
/* Convert short port number from host to network byte order */ 
#define htons(x) ((unsigned short)((x<<8)|(x>>8))) 
 
main() { 
        int     status;         /* For return status */ 
        short   channel;        /* INET channel */ 
        short   channel_1;      /* Template for ACCEPT */ 
        short   sck_parm[2];    /* Socket creation parameter */ 
        short   iosb[4];        /* I/O status block */ 
 
        char    buf[512]; 
        int     buflen = 512;   /* Buffer length */ 
        int     retval; 
        short   port; 
        unsigned char *dummy; 
        unsigned int    r_retlen; 
        int     one=1; 
        struct  SOCKADDRIN local_host, remote_host; 
 
        struct  IL2 { 
                unsigned int il2_length; 
                char *il2_address; 
        } lhst_adrs; 
 
        struct  IL3 { 
                unsigned int il3_length; 
                char *il3_address; 
                unsigned int* il3_retlen; 
        } rhst_adrs; 
 
        struct  dsc$descriptor inet_dev = 
                {10, DSC$K_CLASS_S, DSC$K_DTYPE_T, "TCPIP$DEVICE"}; 
 
 struct  { short len, param; int *ptr; } 
                item_list[] = {{sizeof(one), TCPIP$C_REUSEADDR, (int*)0 }}, 
                options = {sizeof(item_list), TCPIP$C_SOCKOPT, (int*)0 }; 
 
        item_list[0].ptr = &one; 
        options.ptr = (int*)item_list; 
 
        lhst_adrs.il2_length = sizeof local_host; 
        lhst_adrs.il2_address = (char *)&local_host; 
 
        rhst_adrs.il3_length  = sizeof remote_host; 
        rhst_adrs.il3_address = (char*)&remote_host; 
        rhst_adrs.il3_retlen  = &r_retlen; 
 
        sck_parm[0] = TCPIP$C_TCP;                    /* TCP/IP protocol */ 
        sck_parm[1] = INET_PROTYP$C_STREAM;         /* Stream type of socket */ 
        local_host.SIN$W_FAMILY = TCPIP$C_AF_INET;    /* INET family */ 
        local_host.SIN$L_ADDR = TCPIP$C_INADDR_ANY;   /* Any address */ 
 
        while (retval != 1) { 
                printf("Enter local port number:\n"); 
                retval = scanf("%hd", &port); 
                if (retval == 1) 
                        local_host.SIN$W_PORT = htons(port); 
                else scanf("%s",buf);    /* discard bad input */ 
        } 
 
        /* Assign two channels to the device. */ 
        status = sys$assign(&inet_dev, &channel, 0, 0); 
        if (status & 1) 
                status = sys$assign(&inet_dev, &channel_1, 0, 0); 
        if (!(status & 1)) { 
                printf("Failed to assign channel to device.\n"); 
                exit(status); 
        } 
 
       /* Create the socket and set the REUSEADDR option. */ 
       status = sys$qiow(3,             /* Event flag */ 
                        channel,        /* Channel number */ 
                        IO$_SETMODE,    /* I/O function */ 
                        iosb,           /* I/O status block */ 
                        0, 0, 
                        &sck_parm, 0,   /* P1 socket creation parameter */ 
                        0, 0, 
                        &options, 0);   /* P5 socket option descriptor */ 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) { 
                printf("Failed to create the device socket.\n"); 
                exit(status); 
        } 
 
        /* Bind to chosen port number (after REUSEADDR is set above). */ 
        status = sys$qiow(3,            /* Event flag */ 
                        channel,        /* Channel number */ 
                        IO$_SETMODE,    /* I/O function */ 
                        iosb,           /* I/O status block */ 
                        0, 0, 
                        0, 0, 
                        &lhst_adrs,     /* P3 local socket name */ 
                        3,              /* P4 connection backlog */ 
                        0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) { 
                printf("Failed to bind the device socket.\n"); 
                exit(status); 
        } 
 
        /* Accept a connection from a client. */ 
        status = sys$qiow(3,                    /* Event flag */ 
                        channel,                /* Channel number */ 
                        IO$_ACCESS|IO$M_ACCEPT, /* I/O function */ 
                        iosb,                   /* I/O status block */ 
                        0, 0, 
                        0, 0, 
                        &rhst_adrs,             /* P3 Remote IP address*/ 
                        &channel_1,             /* P4 Channel for new socket */ 
                        0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) { 
                printf("Failed to accept a connection from a client.\n"); 
                exit(status); 
        } 
        dummy = (unsigned char *)&remote_host.SIN$L_ADDR; 
        printf("Connection from host: %d.%d.%d.%d, port: %d\n", 
                dummy[0], dummy[1], dummy[2], dummy[3], 
                htons(remote_host.SIN$W_PORT)); 
 
        /* Read I/O buffer. */ 
        status = sys$qiow(3,            /* Event flag */ 
                        channel_1,      /* Channel number */ 
                        IO$_READVBLK,   /* I/O function */ 
                        iosb,           /* I/O status block */ 
                        0, 0, 
                        buf,            /* P1 buffer */ 
                        buflen,         /* P2 buffer length */ 
                        0, 0, 0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) 
                 printf("Failed to read from socket.\n"); 
 
        /* If all is well, print message */ 
        printf ("Received text: %s\n", buf); 
 
        /* Shut down the socket (optional). */ 
        status = sys$qiow(3, 
                        channel_1, 
                        IO$_DEACCESS|IO$M_SHUTDOWN, 
                        iosb, 
                        0, 0, 
                        0, 0, 0, 
                        TCPIP$C_DSC_ALL,    /* P4 Discard all packets */ 
                        0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) 
                printf("Failed to shut down the socket.\n"); 
 
        /* Close the sockets -- accepted and listener (optional). */ 
        status = sys$qiow(3, 
                        channel_1, 
                        IO$_DEACCESS, 
                        iosb, 
                        0, 0, 
                        0, 0, 0, 0, 0, 0); 
        if (status & 1) status = sys$qiow(3, 
                        channel, 
                        IO$_DEACCESS, 
                        iosb, 
                        0, 0, 
                        0, 0, 0, 0, 0, 0); 
        if (status & 1) status = iosb[0]; 
        if (!(status & 1)) 
                printf("Failed to close the socket.\n"); 
 
        /* Deassign the device channels. */ 
        status = sys$dassgn(channel_1); 
        if (status & 1) status = sys$dassgn(channel); 
        if (!(status & 1)) 
        printf("Failed to deassign the channel.\n"); 
} 
 

A.2 UDP/IP Server --- C Socket Example

Example A-2 shows a UDP/IP server using the IPC socket interface. You can access this file online in TCPIP$EXAMPLES:TCPIP$UDP_SERVER_IPC.C.

This example shows you how to create a SOCK_DGRAM (UDP) socket type, bind it, and select it to receive a message on the socket. Error messages are printed to the screen.

This example is portable to UNIX. The include files are conditionally defined for both OpenVMS VAX and Alpha systems, and "perror" is used for error reporting.

The C Socket calls used in this program are:

Depending on your compiler, you can compile and link this program in any of the following ways:

Example A-2 UDP/IP Server Using the C Socket Interface

 
#ifdef VMS 
#include <descrip.h>        /* OpenVMS descriptor information */ 
#include <errno.h>          /* UNIX style error codes for I/O routines */ 
#include <in.h>             /* Internet system constants and structures */ 
#include <inet.h>           /* Network address information */ 
#include <iodef.h>          /* I/O function code definitions */ 
#include <lib$routines.h>   /* LIB$ RTL-routine signatures */ 
#include <netdb.h>          /* Network database library information */ 
#include <signal.h>         /* UNIX style signal value definitions */ 
#include <socket.h>         /* TCP/IP socket definitions */ 
#include <ssdef.h>          /* SS$_<xyz> system service return status codes */ 
#include <starlet.h>        /* System service calls */ 
#include <stdio.h>          /* UNIX 'standard I/O' definitions   */ 
#include <stdlib.h>         /* General utilities */ 
#include <string.h>         /* String handling function definitions */ 
#include <tcpip$inetdef.h>    /* Network definitions */ 
#include <unixio.h>         /* Prototypes for UNIX emulation functions */ 
 
#else 
#include <errno.h> 
#include <sys/types.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <sys/uio.h> 
#include <time.h>  /* timeval declared here */ 
#endif 
 
 
/*-----------------------------------------------------------*/ 
 
cleanup( int socket ) 
{ 
        int    retval; 
 
        /* 
         * Shut down socket completely. 
         */ 
        retval = shutdown(socket,2); 
        if (retval == -1) 
                perror ("shutdown"); 
 
        /* 
         * Close socket. 
         */ 
        retval = close (socket); 
        if (retval) 
        perror ("close"); 
 
        exit( 1 ); 
 
} /* end cleanup */ 
 
/*--------------------------------------------------------------------*/ 
main( int argc, char **argv ) 
{ 
        int     rmask, wmask, emask; 
        int     sock_2;                         /* Socket 2  descriptor      */ 
        int     buflen,fromlen; 
        char    recvbuf[BUFSIZ]; 
static  struct  sockaddr_in sock1_name;     /* Address struct for socket1 */ 
static  struct  sockaddr_in sock2_name;     /* Address struct for socket2 */ 
        int  namelength; 
        struct  hostent         hostentstruct;  /* Storage for hostent data   */ 
        struct  hostent         *hostentptr;    /* Pointer to hostent data    */ 
        static  char            hostname[256];  /* Name of local host         */ 
        int     retval; 
        int     flag; 
        struct  timeval      timeout; 
 
        /* 
         * Check input parameters 
         */ 
        if (argc != 2 ) 
                { 
                printf("Usage: server portnumber.\n"); 
                exit( 1 ); 
                } 
 
        /* 
         * Open socket 2: AF_INET, SOCK_DGRAM. 
         */ 
        if ((sock_2 = socket (AF_INET, SOCK_DGRAM, 0)) == -1) 
                { 
                perror( "socket"); 
                exit( 1 ); 
                } 
 
 
        /* 
         * Get the local host  name. 
         */ 
        retval = gethostname(hostname,sizeof hostname); 
        if (retval) 
                { 
                perror ("gethostname"); 
                cleanup(sock_2); 
                } 
 
 
        /* 
         * Get pointer to network data structure for local host. 
         */ 
        if ((hostentptr = gethostbyname (hostname)) == NULL) 
                { 
                perror( "gethostbyname"); 
                cleanup(sock_2); 
                } 
 
 
        /* 
         * Copy hostent data to safe storage. 
         */ 
        hostentstruct = *hostentptr; 
 
 
        /* 
         * Fill in the address structure for socket 2. 
         */ 
        sock2_name.sin_family = hostentstruct.h_addrtype; 
        sock2_name.sin_port = htons(atoi(argv[1])); 
        sock2_name.sin_addr = * ((struct in_addr *) hostentstruct.h_addr); 
 
 
        /* 
         * Bind name to socket 2. 
         */ 
        retval = bind ( sock_2, 
                        (struct sockaddr*)&sock2_name, 
                        sizeof sock2_name ); 
        if (retval)                       
                { 
                perror("bind"); 
                cleanup(sock_2); 
                } 
 
 
        /* 
         * Select socket to receive message. 
         */ 
        emask = wmask = 0; 
        rmask = (1<<sock_2);  /* set read mask */ 
        timeout.tv_sec = 30; 
        timeout.tv_usec = 0; 
 
        retval = select( 32, &rmask, &wmask, &emask, &timeout ); 
        switch (retval) 
        { 
          case -1: 
                { 
                perror("select"); 
                cleanup(sock_2); 
                } 
          case 0: 
                { 
                printf("Select timed out with status 0.\n"); 
                cleanup(sock_2); 
                } 
          default: 
                if ((rmask & (1<<sock_2)) == 0) 
                        { 
                        printf("Select not reading on sock_2.\n"); 
                        cleanup(sock_2); 
                        } 
          } /*switch*/ 
 
 
        /* 
         * Recvfrom buffer - from sock1 on sock2. 
         */ 
 
        buflen = sizeof(recvbuf); 
        fromlen = sizeof(sock1_name); 
        flag = 0;          /* flag may be MSG_OOB and/or MSG_PEEK */ 
 
        retval = recvfrom( sock_2, 
                           recvbuf, 
                           buflen, 
                           flag, 
                           (struct sockaddr*)&sock1_name, 
                           &fromlen); 
        if (retval == -1) 
                perror("recvfrom"); 
             else 
                printf (" %s\n", recvbuf); 
 
        /* 
         * Call cleanup to shut down and close socket. 
         */ 
 
         cleanup(sock_2); 
 
  } /* end main */ 

A.3 TCP/IP Server --- C Socket Example

Example A-3 shows a TCP/IP server using the C Socket interface. You can access this file online in TCPIP$EXAMPLES:TCPIP$TCP_SERVER_IPC.C.

This example creates a SOCK_STREAM (TCP) socket type, binds and listens on the socket, receives a message and closes the connection. Error messages are printed to the screen.

This example is portable to UNIX. The include files are conditionally defined for both OpenVMS VAX and Alpha systems, and "perror" is used for error reporting.

This example uses the following C Socket routines:

Depending on your compiler, you can compile and link this program in any of the following ways:

Example A-3 TCP/IP Server Using the C Socket Interface

#ifdef VMS 
#include <descrip.h>        /* OpenVMS descriptor information */ 
#include <in.h>             /* Internet system constants and structures */ 
#include <inet.h>           /* Network address information */ 
#include <iodef.h>          /* I/O function code definitions */ 
#include <lib$routines.h>   /* LIB$ RTL-routine signatures */ 
#include <netdb.h>          /* Network database library information */ 
#include <signal.h>         /* UNIX style signal value definitions */ 
#include <socket.h>         /* TCP/IP socket definitions */ 
#include <ssdef.h>          /* SS$_<xyz> system service return status codes */ 
#include <starlet.h>        /* System service calls */ 
#include <stdio.h>          /* UNIX 'standard I/O' definitions   */ 
#include <stdlib.h>         /* General utilities */ 
#include <string.h>         /* String handling function definitions */ 
#include <tcpip$inetdef.h>    /* Network definitions */ 
#include <unixio.h>         /* Prototypes for UNIX emulation functions */ 
 
#else 
#include <errno.h> 
#include <sys/types.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <sys/uio.h> 
 
#endif 
 
/*-----------------------------------------------------------*/ 
 
cleanup( int how_many, int sock1, int sock2 ) 
{ 
        int retval; 
 
        /* 
         * Shut down and close sock1 completely. 
         */ 
        retval = shutdown(sock1,2); 
        if (retval == -1) 
                perror ("shutdown"); 
 
        retval = close (sock1); 
        if (retval) 
                perror ("close"); 
 
 
        /* 
         * If given, shutdown and close sock2. 
         */ 
        if (how_many == 2) 
        { 
                retval = shutdown(sock2,2); 
                if (retval == -1) 
                        perror ("shutdown"); 
 
                retval = close (sock2); 
                if (retval) 
                        perror ("close"); 
        } 
 
        exit( 1 ); 
 
} /* end cleanup*/ 
 
 
/*--------------------------------------------------------------------*/ 
main( int argc, char **argv ) 
{ 
 
        int     sock_2, sock_3;                /* sockets */ 
        static  char    message[BUFSIZ]; 
static  struct  sockaddr_in     sock2_name;    /* Address struct for socket2 */ 
static  struct  sockaddr_in     retsock2_name; /* Address struct for socket2 */ 
        struct  hostent         hostentstruct; /* Storage for hostent data   */ 
        struct  hostent         *hostentptr;   /* Pointer to hostent data    */ 
        static  char            hostname[256]; /* Name of local host         */ 
        int     flag; 
        int     retval;                        /* Helpful for debugging */ 
        int     namelength;   
 
 
        /* 
         * Check input parameters. 
         */ 
        if (argc != 2 ) 
                { 
                printf("Usage: server portnumber.\n"); 
                exit( 1 ); 
                } 
 
        /* 
         * Open socket 2: AF_INET, SOCK_STREAM. 
         */ 
        if ((sock_2 = socket (AF_INET, SOCK_STREAM, 0)) == -1) 
                { 
                perror( "socket"); 
                exit( 1 ); 
                } 
 
        /* 
         * Get the host local name. 
         */ 
        retval = gethostname(hostname,sizeof hostname); 
        if (retval) 
                { 
                perror ("gethostname"); 
                cleanup (1, sock_2, 0); 
                } 
 
        /* 
         * Get pointer to network data structure for socket 2. 
         */ 
        if ((hostentptr = gethostbyname (hostname)) == NULL) 
                { 
                perror( "gethostbyname"); 
                cleanup(1, sock_2, 0); 
                } 
 
        /* 
         * Copy hostent data to safe storage. 
         */ 
        hostentstruct = *hostentptr; 
 
        /* 
         * Fill in the name & address structure for socket 2. 
         */ 
        sock2_name.sin_family = hostentstruct.h_addrtype; 
        sock2_name.sin_port = htons(atoi(argv[1])); 
        sock2_name.sin_addr = * ((struct in_addr *) hostentstruct.h_addr); 
 
        /* 
         * Bind name to socket 2. 
         */ 
        retval = bind ( sock_2, 
                        (struct sockaddr*)&sock2_name, 
                        sizeof sock2_name ); 
        if (retval) 
                { 
                perror("bind"); 
                cleanup(1, sock_2, 0); 
                } 
 
        /* 
         * Listen on socket 2 for connections. 
         */ 
        retval = listen (sock_2, 5); 
        if (retval) 
                { 
                perror("listen"); 
                cleanup(1, sock_2, 0); 
                } 
 
        /* 
         * Accept connection from socket 2:      
         * accepted connection will be on socket 3. 
         */ 
        namelength = sizeof (sock2_name); 
        sock_3 = accept (sock_2, (struct sockaddr*)&sock2_name, &namelength); 
        if (sock_3 == -1) 
                { 
                perror ("accept"); 
                cleanup( 2, sock_2, sock_3); 
                } 
 
        /* 
         * Receive message from socket 1. 
         */ 
        flag = 0; /* maybe 0 or MSG_OOB or MSG_PEEK */ 
 
        retval = recv(sock_3, message ,sizeof (message), flag); 
        if (retval == -1) 
                { 
                perror ("receive"); 
                cleanup( 2, sock_2, sock_3); 
                } 
           else 
              printf (" %s\n", message); 
 
        /* 
         * Call cleanup to shut down and close sockets. 
         */ 
        cleanup(2, sock_2, sock_3); 
 
 } /* end main */ 
 


Previous Next Contents Index