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

Previous | Contents

Example 2-23 shows a TCP server using the MSG_OOB flag with the send() routine.

Example 2-23 Writing OOB Data Using C Socket Programming

    /* This program accepts a connection on TCP port 1234, sends the string,
       "Hello, world!", waits two seconds, sends an urgent BEL (^G), waits
       another two seconds, repeats the Hello message, and terminates. */

    #include <types.h>
    #include <in.h>
    #include <socket.h>
    #include <unixio.h>

    #define PORTNUM 1234

    main() {
       struct sockaddr_in lcladdr;
       int r, s, one = 1;
       char *message = "Hello, world!\r\n",
            *oob_message = "\007";

       lcladdr.sin_family = AF_INET;
       lcladdr.sin_addr.s_addr = INADDR_ANY;
       lcladdr.sin_port = htons(PORTNUM);

       if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror("socket");
       if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
          perror("setsockopt");
       if (bind(s, &lcladdr, sizeof(lcladdr))) perror("bind");
       if (listen(s, 1)) perror("listen");
       if ((r = accept(s, 0, 0)) < 0) perror("accept");
       if (send(r, message, strlen(message), 0) != strlen(message))
          perror("send");
       sleep(2);
       if (send(r,(1) oob_message,(2)
       strlen(oob_message),(3) MSG_OOB)(4) !=
           strlen(oob_message)) perror("send");
       sleep(2);
       if (send(r, message, strlen(message), 0) != strlen(message))
          perror("send");
       sleep(2);
       if (close(r)) perror("close");
       if (close(s)) perror("close");
    }

The send() routine is used to send OOB data to a remote socket, as follows:

1. r specifies the remote socket descriptor connected to the local socket as a result of a call to the socket() routine.
2. oob_message is the buffer containing the OOB data.
3. strlen(oob_message) specifies the length, in bytes, of the buffer containing the out-of-band data.
4. MSG_OOB is the flag that indicates the data will be sent out-of-band.

# 2.14 Writing Data and Broadcast Messages (UDP)

An application that uses UDP can write to a remote host. Broadcasting means you send datagrams in one operation to all remote hosts on the local network.

If the internet pseudodevice allows broadcasting, the local host can broadcast datagrams to all the hosts on the local network. To broadcast, you must set the socket. The broadcast address takes the form of a remote host address. The system manager sets up this address on the local host for each subnet or network the host can access.

# 2.15 Sending a Datagram (UDP)

Client applications that use UDP can send datagrams to one or many hosts. In both cases, specify the remote socket names.

## 2.15.1 Sending Datagrams with OpenVMS System Services

You can use either of the following methods to send datagrams:

- To send datagrams from the local host to one remote host, issue the $QIO system service with the IO$_ACCESS function modifier. This allows you to specify the remote socket name once, then use the IO$_WRITEVBLK function to send each datagram without specifying the socket name again.
- To send datagrams from the local host to several remote hosts, issue the $QIO system service with the IO$_WRITEVBLK function modifier, and specify the remote socket name in the p3 argument field.

## 2.15.2 Broadcasting Datagrams with OpenVMS System Services

To broadcast datagrams, issue a $QIO system service command with the IO$_WRITEVBLK function.

Before issuing broadcast messages, the application must issue the IO$_SETMODE function. This sets the broadcast option in the socket. The process must have a system UIC, and a SYSPRV, BYPASS, or OPER privilege to issue broadcast messages. However, the system manager can disable privilege checking with the UCX command SET PROTOCOL UDP /BROADCAST. For more information, refer to DIGITAL TCP/IP Services for OpenVMS Management.

## 2.15.3 Broadcasting Datagrams with a C Socket Interface

You can broadcast datagrams by calling the sendto() routine.

# 2.16 Closing and Deleting a Socket

Closing a socket means that the program can no longer transmit data. Depending on how you close the socket, the program can receive data until the peer program also closes the socket.

When a remote system closes a socket, notification is not immediate. Another thread can erroneously attempt to use the socket.

If you send data to a closed socket, you might not receive an appropriate error message. Set the UCX$FULL_DUPLEX_CLOSE socket option if you want to have your application notified of an error when it sends data on a socket that has already been closed by the peer.

When you delete a socket, all pending messages queued for transmission are sent to the receiving socket before closing the connection.

## 2.16.1 Closing and Deleting with OpenVMS System Services

Make the following calls to close and delete a socket:

1. $QIO(IO$_DEACCESS) --- Stops transmitting data and closes the socket.
2. $DASSGN --- Deletes the internet pseudodevice and deassigns the I/O channel previously acquired with the $ASSIGN service.

Example 2-24 shows a TCP client using OpenVMS system services to close and delete a socket.

Example 2-24 Closing and Deleting a Socket Using OpenVMS System Services

        /* Attempt to Closet the socket. */
        sysSrvSts = sys$qiow( 0,               /* efn.v | 0 */
                              IOChannel,       /* chan.v */
                              IO$_DEACCESS,    /* func.v */
                              &iosb,           /* iosb.r | 0 */
                              0, 0,            /* astadr, astprm: UNUSED */
                              0, 0, 0, 0, 0, 0 /* p1 -> p6 UNUSED */ );
        sys$dassgn( IOChannel );

## 2.16.2 Closing and Deleting with a C Socket Interface

Example 2-25 shows a TCP/IP client using the close() routine to close and delete a socket.

Example 2-25 Closing and Deleting a Socket Using C Socket Programming

    #include  <errno.h>
    #include  <types.h>
    #include  <stdio.h>
    #include  <socket.h>
    #include  <in.h>
    #include  <netdb.h>      /* change hostent to comply with BSD 4.3*/
    #include  <inet.h>
    #include  <ucx$inetdef.h>     /* INET symbol definitions */
       .
       .
       .
    main(argc,argv)
    int  argc;
    char **argv;
    {

            int     sock_1;                      /* socket */
    static  char   message[] = "Hi there.";
    static  struct  sockaddr_in sock2_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  shut = FALSE;            /* flag to cleanup */

         /*
          * Close socket.
          */
         retval = close (socket);(1)
         if (retval)
                 perror ("close");

         exit();

    } /* end cleanup */

(1) The socket argument for the close() routine closes the socket and deletes the socket descriptor previously defined by a socket() routine.

# 2.17 Shutting Down Sockets

You can shut down a socket prior to closing and deleting it. The shutdown operation allows you to shut down communication one process at a time. This maintains unidirectional rather than normal bidirectional connections, allowing you to shut down communications on receive, transmit, or both data queues. For example, if you no longer want to transmit data but want to continue receiving data, shut down the transmit side of the socket connection and keep open the receive side of the connection.

## 2.17.1 Shutting Down a Socket with OpenVMS System Services

To shut down a socket, issue the IO$_DEACCESS function with the IO$M_SHUTDOWN modifier. This function shuts down all or part of the full-duplex connection on the device socket.

The application uses subfunctions or flags to specify whether pending I/O operations are completed or discarded before the IO$_DEACCESS function completes. After the IO$_DEACCESS function completes, messages can no longer be transmitted or received.

Example 2-26 shows a TCP server using the IO$_DEACCESS function and the IO$M_SHUTDOWN modifier to shut down all communications. In this example, no data is received or transmitted and all queued data is discarded.

Example 2-26 Shutting Down a Socket Using OpenVMS System Services

    /*
    **
    ** Shutdown this server.
    **
    */
        sysSrvSts = sys$qiow( 0,                 /* efn.v | 0 */
                              IOChannel,      /* chan.v */
                              IO$_DEACCESS |
                                  IO$M_SHUTDOWN, /* func.v */
                              &iosb,             /* iosb.r | 0 */
                              0, 0,              /* astadr, astprm: UNUSED */
                              0, 0, 0,           /* p1, p2, p3 UNUSED */
                              UCX$C_DSC_ALL,     /* p4.v mode to shutdown */
                              0, 0               /* p5, p6 UNUSED */   );

        if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */
           ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */
            errorExit( sysSrvSts, iosb.cond_value );
        else
            printf( "    SUCCEEDED in shutting down this server.\n" );

        sys$dassgn( IOChannel );

## 2.17.2 Shutting Down with a C Socket Interface

Example 2-27 shows a TCP/IP client using the shutdown() routine.

Example 2-27 Shutting Down a Socket Using C Socket Programming

    #include  <errno.h>
    #include  <types.h>
    #include  <stdio.h>
    #include  <socket.h>
    #include  <in.h>
    #include  <netdb.h>      /* change hostent to comply with BSD 4.3*/
    #include  <inet.h>
    #include  <ucx$inetdef.h>     /* INET symbol definitions */
       .
       .
       .

            /*
             * Call cleanup to shutdown and close socket.
             */
            cleanup(sock_1);

     } /* end main */

    /*-----------------------------------------------------------*/

    cleanup(socket)
    int        socket;

    {
            int        retval;

            /*
             * Shutdown socket  completely.
             */
            retval = shutdown(socket(1),(2)3)(2);
            if (retval == -1)
                    perror ("shutdown");

            /*
             * Close socket.
             */
            retval = close (socket);
            if (retval)
                    perror ("close");

            exit();

    } /* end cleanup */

1. socket specifies the socket descriptor for the socket being shut down.
2. INET$C_DSC_ALL= 3 closes both the transmit and receive socket queues.
   The other valid socket descriptor values are:
   - INET$C_DSC_RCV = 1 closes the receive socket queue.
   - INET$C_DSC_SND = 2 closes the transmit socket queue.
   The close() routine then closes the socket, deleting the socket descriptor.

   # 2.18 Canceling I/O Operations

   The $CANCEL system service cancels pending I/O requests on a specific channel or socket. This includes all I/O requests queued and in progress.

   There is no C Socket routine for this operation. The C Socket library functions are synchronous.

   # 2.19 Application Development Tools for OpenVMS System Services Programming

   DIGITAL provides include files, data types, and support routines to help with OpenVMS system services programming.

   ## 2.19.1 Include Files for OpenVMS System Services Programming

   The include files provide definitions for constants. The available include files are as follows:

   Table 2-5 OpenVMS System Service Include Files
   Include File | Description
   --- | ---
   descrip.h | OpenVMS descriptor information
   in.h | Internet system constants and structures
   inet.h | Network address information
   iodef.h | I/O function code definitions
   lib$routines.h | Run-time library routine signatures
   netdb.h | Network database library information
   signal.h | UNIX-style signal value definitions
   socket.h | TCP/IP socket definitions
   ssdef.h | System services return status
   starlet.h | System services calls
   stdio.h | Standard UNIX I/O definitions
   stdlib.h | General utilities
   string.h | String handling function definitions
   ucx$inetdef.h | UCX network definitions

   ## 2.19.2 Data Structures for OpenVMS System Services Programming

   The data types or data structures locally define unsigned entities. The following lists the available data structures.

       */
       **  Locally defined data structures.
       /*
           typedef struct IosbStruct
               {
               unsigned short cond_value;
               unsigned short count;
               unsigned long  info;
               }    iosbType,     /* For one occurrence */
                   *iosbPtr;      /* For a pointer to an occurrence */

           typedef struct SocketParamStruct
               {
               unsigned short protocol;
               unsigned char  type;
               unsigned char  family;
               }    socketParamType, /* For one occurrence */
                   *socketParamPtr;  /* For a pointer to an occurrence*/

       /*

       **
       ** IP Address information.
       **
       */
           typedef struct  IPAddrInfoStruct
               {
               unsigned int   length;
                        char *address;
               unsigned int  *retLenPtr;
               }    iPAddrInfoType, /* For one occurrence */
                   *iPAddrInfoPtr;  /* For a pointer to an occurrence*/

       /*
       **
       ** Item List structure for getting and setting socket options.
       **
       */
           typedef struct  ILSockOptStruct
               {
               unsigned short  length;
               unsigned short  code;
                        char  *optStructAddr;
               }    iLSockOptType,  /* For one occurrence */
                   *iLSockOptPtr,   /* For a pointer to an occurrence*/
                    iLSockOptArr[]; /* For an array of occurrences*/

       /*
       **
       ** Set socket options structure.
       **
       */
           typedef struct  SetSockOptStruct
               {
               unsigned short  length;
               unsigned short  code;
                        char  *optBuffAddr;
               }    setSockOptType,  /* For one occurrence */
                   *setSockOptPtr,   /* For a pointer to an occurrence*/
                    setSockOptArr[]; /* For an array of occurrences*/
       /*
       **
       ** Get socket options structure.
       **
       */
             typedef struct  GetSockOptStruct
                 {
                 unsigned short  length;
                 unsigned short  code;
                          char  *optBuffAddr;
                 int            *retLength;
                 }    getSockOptType,  /* For one occurrence */
                     *getSockOptPtr,   /* For a pointer to an occurrence*/
                      getSockOptArr[]; /* For an array of occurrences*/
       /*
       /*
       **
       **  MACRO DEFINITIONS
       **
       */
       **
       */

       #define MaxBuff              80
       #define SERVER_PORT_NUMBER   5321
       #define SERVER_QLENGTH       4

   ## 2.19.3 Support Routines for OpenVMS System Services Programming

   The support routines provide two functions. One routine closes and deassigns the socket from the network device. The other routine signals errors and exits. The contents of the support routines are as follows:

       (1)

       **  FUNCTION: cleanup()
       **
       **  Close the socket and deassign it from the network device.
       **
       **  RETURNS: none
       **
       */
       static void cleanup( int IOChannel )
       {
           iosbType   iosb;             /* I/O result status */
           int        sysSrvSts;        /* System Service status */

           /* Attempt to Closet the socket. */
           sysSrvSts = sys$qiow( 0,               /* efn.v | 0 */
                                 IOChannel,       /* chan.v */
                                 IO$_DEACCESS,    /* func.v */
                                 &iosb,           /* iosb.r | 0 */
                                 0, 0,            /* astadr, astprm: UNUSED */
                                 0, 0, 0, 0, 0, 0 /* p1 -> p6 UNUSED */ );
           sys$dassgn( IOChannel );

       } /* END cleanup() */

       (2)
       **  FUNCTION: errorExit()
       **
       **  Signal any errors and exit.
       **
       **  RETURNS: none
       **
       */
       static void errorExit( int            sysSrvSts,  /* System Service status */
                              unsigned short iosbCond )  /* I/O result status */
       {
           if(( sysSrvSts & 1  ) != 1  ) /* Validate the system service status. */
               lib$signal( sysSrvSts );

           if((  iosbCond & 1  ) != 1 )  /* Validate the IO status. */
               lib$signal( iosbCond );

           exit( SS$_NORMAL );
       } /* END errorExit() */

   1. The support routine that closes and deassigns the socket.
   2. The support routine that signals errors and exists.

   # 2.20 Compiling and Linking DIGITAL C Language Programs

   The examples in this chapter were written to use the VAX C compiler but should also be compatible with the DEC C compiler. However, if you are using the DEC C or C++ compiler and are having difficulty compiling some of these programs, DIGITAL recommends using either the VAX C compiler or the DEC C or C++ compiler with the following qualifiers:

       $ /STANDARD=VAXC/PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES

   ## 2.20.1 Linking Programs Compiled by DEC C

   If you compile your program using DEC C, issue the LINK command as follows:

       $ LINK MAIN

   Do not specify SYS$LIBRARY:UCX$IPC.OLB because the DEC C compiler does not use this library. Also, you do not need to specify UCX$IPC_SHR because the DEC C compiler uses this shareable image by default.

   ## 2.20.2 Linking Programs Compiled by VAX C

   If you compile your program using VAX C, issue the LINK command as follows:

       $ LINK MAIN, SYS$LIBRARY:UCX$IPC/LIB, SYS$INPUT/OPTIONS
       SYS$SHARE:UCX$IPC_SHR/SHARE

   Use the /OPTIONS qualifier for executable images. UCX$IPC.OLB contains the transfer vectors used to resolve the socket routine references to the VAXCRTL.

   # Chapter 3
   Using the OpenVMS System Services

   This chapter describes how to use the $QIO system service and its data structures with DIGITAL TCP/IP Services for OpenVMS.

   After you create an internet pseudodevice and assign a channel to it, use the $QIO system service for I/O operations.

   # 3.1 $QIO System Service Variations

   The two variations of the $QIO system service are:

   - Queue I/O Request ($QIO) --- completes asynchronously. It returns to the caller immediately after queuing the I/O request, without waiting for the I/O operation to complete.
   - Queue I/O Request and Wait ($QIOW) --- completes synchronously. It returns to the caller after the I/O operation completes.

   The only difference between the $QIO and $QIOW service calls is the service name. The service call parameters are the same.

   # 3.2 $QIO Syntax

   The $QIO system service has the following syntax:

   SYS$QIO [efn],chan,func[,iosb] [,astadr][,astprm][,p1][,p2] [,p3][,p4][,p5][,p6]

   Table 3-1 describes each argument.

   Table 3-1 $QIO Arguments
   Argument | Description
   --- | ---
   efn | Event flag number
   chan | I/O channel
   func | Internet pseudodevice function code and modifier
   iosb | I/O status block
   astadr | AST (asynchronous system trap) service routine
   astprm | AST parameter to be passed
   p1, p2, p3, p4, p5, p6 | Function-dependent $QIO parameters

   ## 3.2.1 $QIO Function-Dependent Parameters

   Table 3-2 contains the symbol definitions for the $QIO arguments p1 through p6. Use the standard mechanism for the programming language you are using to include these symbol definitions in your program.

   Table 3-2 Internet Symbol Definition Files
   File Name | Language
   --- | ---
   UCX$INETDEF.H | DEC C or VAX C
   UCX$INETDEF.FOR | VAX Fortran
   UCX$INETDEF.PAS | VAX PASCAL
   UCX$INETDEF.MAR | MACRO-32
   UCX$INETDEF.PLI | VAX PL/1
   UCX$INETDEF.R32 | BLISS-32
   UCX$INETDEF.ADA | VAX ADA
   UCX$INETDEF.BAS | VAX BASIC

   # 3.3 Common $QIO Functions

   Table 3-3 lists the $QIO functions commonly used in internet applications.

   > Note

   > The IO$_SETMODE and IO$_SETCHAR service calls function identically. All references to the IO$_SETMODE system call, its arguments, options, modifiers, and condition values returned also apply to the IO$_SETCHAR system call, which is not explicitly described in this book.

   Table 3-3 $QIO Functions
   Function | Description
   --- | ---
   QIO$(IO$_SETMODE) QIO$(IO$_SETCHAR) | Creates the socket by setting the internet domain, protocol (socket) type, and protocol of the device socket.
   | Binds a name (local address and port) to the socket.
   | Defines an internet pseudodevice as a listener on a TCP/IP server.
   | Specifies socket options.
   QIO$(IO$_ACCESS) | Initiates a connection request by a client to a remote host TCP/IP.
   | Specifies the peer where you can send datagrams.
   | Accepts a connection request from a TCP/IP client when used with the IO$M_ACCEPT modifier.
   QIO$(IO$_WRITEVBLK) | Writes data (virtual block) from local host to remote host for stream sockets, datagrams, and raw IP.
   QIO$(IO$_READVBLK) | Reads data (virtual block) from remote host to local host for TCP/IP, UDP/IP, or IP layers.
   QIO$(IO$_DEACCESS) | Disconnects the link established between two communication agents through an ACCESS function TCP/IP.
   | Shuts down the communication link when used with the IO$M_SHUTDOWN modifier. You can shut down the receive, transmit, or both portions of the link.
   QIO$(IO$_SENSEMODE) | Obtains socket information.

   # 3.4 $QIO Arguments

   You pass two types of arguments with $QIO system services: function-independent arguments and function-dependent arguments. The following sections provide information on $QIO system service arguments.

   ## 3.4.1 Device- and Function-Independent $QIO Arguments

   Table 3-4 describes the device- and function-independent $QIO arguments.

   Table 3-4 Device- and Function-Independent Arguments
   Argument | Description
   --- | ---
   efn | A longword value of the event flag number that the $QIO system service sets when the I/O operation completes.
   chan | A word value that contains the number of the I/O channel. The $QIO system service uses only the low-order word.
   func | A longword value that specifies the internet pseudodevice functions and function modifiers that define the specified operation. Function modifiers affect the operation of a specified function. In MACRO-32, you use the exclamation point (!) to separate the function and the modifier. In DEC C, you use the vertical bar (|). This book uses the vertical bar (|) in text.
   (iosb) | The I/O status block that receives the final status message for the I/O operation. The iosb argument is the address of the quadword I/O status block.
   astadr | Address of the asynchronous system trap (AST) routine to be executed when the I/O operation is completed.
   astprm | Longword value containing the value to be passed to the AST routine.

   Previous | Next | Contents