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

Previous | Contents

An IO$_DEACCESS function prevents the user process that issued the function from sending any more data. It also ensures successful delivery of all data queued before the IO$_DEACCESS function was issued, unless there is a fatal error. A fatal error will be signaled. The user may continue to receive data until it is signaled that the connection peer has closed the connection.

Before a receiving process with a connection-oriented protocol is notified about a synchronous disconnection, all the data that the peer sent is received.

You can specify a wait time or time-to-linger socket parameter (UCX$C_LINGER option) for transmission completion before disconnecting the connection. Use the IO$_SETMODE or IO$_SETCHAR function to set and clear the UCX$C_LINGER option.

If you set the UCX$C_LINGER option, a $QIO call that uses the IO$_DEACCESS function allows data queued to the socket to arrive at the destination. The system is blocked until data arrives at the remote socket. The socket data structure remains open for the duration of the TCP idle time interval.

If you do not set the UCX$C_LINGER option (option is set to 0), a $QIO call that uses the IO$_DEACCESS function discards any data queued to the socket and deallocates the socket data structure.

> Note

> For compatibility with UNIX TCP/IP, the UCX implementation of TCP/IP forces a time-to-linger of 2 minutes on stream sockets.

The equivalent C Socket function is close() or shutdown().

## ARGUMENTS

> ### p4

> UCX usage | flags
> type | byte (unsigned)
> access | read only
> mechanism | by value

> This argument is used only with the IO$M_SHUTDOWN function modifier. The following table lists the IO$M_SHUTDOWN flags (defined in the UCX$INETDEF symbol definition file) that you can use to specify the disposition of pending I/O operations.

> Shutdown Flag | Description
> --- | ---
> UCX$C_DSC_RCV | Discards messages from the receive queue and disallows further receiving. Pending messages in the receive queue for this connection are discarded. The socket is put in CANTRCVMORE state.
> UCX$C_DSC_SND | Discards messages from the send queue and disallows further sending. Pending messages in the transmit queue for this connection are discarded. The socket is put in CANTSNDMORE state.
> UCX$C_DSC_ALL | Discards all messages and disallows both sending and receiving (socket is put in the CANTRCVMORE and CANTSNDMORE states). All pending messages are discarded. Specifying this flag has the same effect as issuing a $CANCEL function followed by an IO$_DEACCESS function without any flags.

## Function Modifiers

> IO$M_SHUTDOWN | Causes all or part of the full-duplex connection on the device socket to be shut down. The p4 parameter specifies shutdown flags.
> IO$M_NOW | Regardless of a $QIO or $QIOW, if the system detects a condition that would cause the I/O operation to block, the system completes the I/O operation and returns the error code SS$_SUSPENDED.

## Condition Values Returned

> SS$_ABORT | Programming error, INET management error, or hardware error. The execution of the I/O function aborts. A disconnect was requested on a connection that already started a disconnect operation.
> SS$_BADPARAM | Programming error. You specified a $QIO function using an invalid parameter. You tried to execute one of the I/O functions without specifying a device socket. Instead, you should first create a device socket by issuing a $QIO with the IO$_SETMODE function and the proper parameters.
> SS$_CANCEL | Warning code. The I/O operation canceled by executing a $CANCEL system service routine.
> SS$_DEVINACT | INET management error. The driver was not started. You must execute a UCX START COMMUNICATION before issuing a $QIO operation.
> SS$_DEVNOTMOUNT | INET management error. You improperly executed the INET startup procedure. The driver was loaded, but the INET_ACP function was not activated.
> SS$_NOLINKS | Programming error because of one of the following reasons: The socket was not connected (TCP/IP) or an INET port and address were not specified with an IO$_ACCESS (UDP/IP) or IP. You tried to disconnect an unconnected socket.
> SS$_SHUT | The network is being shut down.

# IO$_READVBLK

> Read functions transfer data received from an internet host and store that data in system-dynamic space on the virtual memory address of the user process. The TCP/IP software provides the READ I/O function code IO$_READVBLK, which reads a virtual block of a stream socket, datagram, or raw socket.

> Received messages are stored in system-dynamic memory and copied to user buffers when the software issues a read operation.

> If you specify multiple buffers, the buffers are filled in the order specified in the p6 list.

> The TCP/IP software fills in these user buffers according to the protocol (socket type).

> For TCP/IP (stream socket), data is buffered in system space as a stream of bytes. The user buffer specified with a $QIO is filled in with data that is being buffered in system space. The I/O is completed when there is no more data in the system space, or there is no more available space in the user buffer. Data that is buffered in the system space but did not fit in the user buffer is available to the user in subsequent $QIOs. No data is discarded or lost.

> Datagram and raw socket data is buffered in system space as a chain of records. The user buffer specified with a $QIO is filled in with data that is being buffered in one record in system space. One I/O operation reads data from one record. The I/O completes when there is no more space in the user buffer or when all data from the record has been transferred to the user buffer. Data remaining in the current record in system space that did not fit in the user buffer is discarded. A subsequent $QIO reads data from the next record buffered in system space.

> Use the UCX SHOW DEVICE_SOCKET /FULL command to display counters related to read operations.

> The equivalent C Socket function is the recv*() or read() routine.

> Three programming examples for the IO$_READVBLK routine follow this command description. Example 4-9 uses the MACRO-32 programming language to read a vectored buffer. Example 4-10 uses the C programming language to read a vectored buffer. Example 4-11 uses the C programming language to read from an INET driver.

## ARGUMENTS

> ### p1

> UCX usage | buffer
> type | longword (unsigned)
> access | read only
> mechanism | by reference

> The p1 argument specifies the starting virtual address of the buffer that is to receive the data.

> ### p2

> UCX usage | buffer length
> type | longword (unsigned)
> access | read only
> mechanism | by value

> The p2 argument specifies the size (in bytes) of the buffer that is to receive the data.

> ### p3

> UCX usage | remote socket name for the source of the message
> type | longword (unsigned)
> access | read only
> mechanism | by descriptor

> The p3 argument specifies the address of a UCX item_list_3 descriptor with a buffer that contains the remote socket name of the source of the message. The remote socket is composed of the remote port and host internet address.

> The parameter name for the descriptor is UCX$C_SOCK_NAME, which is defined in the UCX$INETDEF symbol definition file.

> ### p4

> UCX usage | flags
> type | word (unsigned)
> access | read only
> mechanism | by value

> The p4 argument specifies the flags for the read operation. The valid flags are described in Table 4-8.

> Table 4-8 Valid Flags for the p4 Argument
> Flag | Description
> --- | ---
> UCX$C_MSG_OOB | Reads an out-of-band byte.
> UCX$C_MSG_PEEK | Reads a message but leaves the message in the queue. Another read operation shows the same message.
> UCX$C_MSG_NBIO | Does not block the I/O operation if the receive queue is empty. Similar to using IO$M_NOWAIT.
> UCX$C_MSG_PURGE | Flushes data from the queue. Similar to using IO$M_PURGE.
> UCX$C_MSG_BLOCKALL | Blocks the completion of the operation until the buffer is filled completely or until the connection is closed. Similar to using IO$M_LOCKBUF.

> ### p6

> UCX usage | UCX item_list_2
> type | longword (unsigned)
> access | read only
> mechanism | by descriptor

> The p6 argument specifies the address for the descriptor of an output parameter list.

> The maximum number of buffers you can specify with the p6 argument is 16.

> If you use the p1 and p2 arguments, do not use the p6 argument; they are mutually exclusive. You either use p1 and p2, or you use p6 instead. The software first checks to see if the p1 argument is used. If p1 is not used, the software checks to see if the p6 argument is being used. If neither the p1 nor the p6 arguments are used, the software returns an error code.

> The transfer-length value returned in the I/O status block is the total number of bytes transferred to the buffer or multiple buffers.

## Function Modifiers

> IO$M_INTERRUPT | Reads an out-of-band (OOB) message. This has the same effect as specifying the UCX$C_MSG_OOB flag.
> | On receiving a TCP/IP OOB character, TCP/IP stores the pointer in the received stream with the character that precedes the OOB character.
> | A read operation with a user-buffer size larger than the size of the received stream up to the OOB character completes and returns to the user the received stream up to, but not including, the OOB character.
> | To determine whether the socket must issue more read $QIOs before getting all the characters from the stream preceding an OOB character, poll the socket. To do this, issue a $QIO with the $IO_SENSEMODE function, and the UCX$C_IOCTL subfunction that specifies the SIOCATMARK command. The SIOCATMARK values are as follows: 0 = Issue more read QIOs to read more data before reading the OOB. 1 = The next read QIO will return the OOB.
> | Polling a socket is particularly useful when the OOBINLINE socket option is set. When the OOBINLINE is set, TCP/IP reads the OOB character with the characters in the stream (IO$_READVBLK), but not before reading the preceding characters. Use this polling mechanism to determine whether the first character in the user buffer on the next read is an OOB character.
> | On a socket with the OOBINLINE option set to clear, a received OOB will always be read by issuing a $QIO with either the IO$_READVBLK!IO$M_INTERRUPT or IO$_READVBLK and the UCX$C_MSG_OOB flag set. This can occur, regardless of how many preceding characters in the stream have been returned to the user.
> IO$M_LOCKBUF | Blocks the completion of the I/O operation until the user buffer is completely filled or until the connection is closed. This is particularly useful when you want to minimize the number of $QIO commands issued to read a data stream of a particular size. This function code is supported only for stream protocols.
> IO$M_NOWAIT | Regardless of a $QIO or $QIOW, if the system detects a condition that would cause the I/O operation to block, the system completes the I/O operation and returns the error code SS$_SUSPENDED.
> IO$M_PURGE | Flushes data from the device socket receive queue (discards data). If the user buffer is larger than the amount of data in the queue, all data in the queue is flushed. This function works in the same manner for both datagram and stream sockets.

## Condition Values Returned

> SS$_ABORT | Programming error, INET management error, or hardware error. The execution of the I/O was aborted.
> SS$_ACCVIO | Programming error. You tried to access an invalid memory location or buffer.
> SS$_BADPARAM | Programming error. You used one of the following methods to specify a $QIO function with an invalid parameter: You executed an I/O function without specifying a device socket. You must first issue a $QIO with the IO$_SETMODE function and the proper parameters to create the device socket. You issued an IO$_READVBLK or IO$_WRITEVBLK function that does not specify a correct buffer address ( p1, p5 or p6 are null). You issued an IO$_READVBLK or IO$_WRITEVBLK function that specifies an invalid vectored buffer ( p5 or p6 are invalid address descriptors). The socket has the OOBINLINE option set, or there is no OOB character in the socket's OOB queue because the character was either already read or never received. This condition happens only if you use the IO$M_INTERRUPT modifier or set the UCX$C_MSG_OOB flag with IO$_READVBLK.
> SS$_CANCEL | Warning code. The I/O operation canceled by executing a $CANCEL system service routine.
> SS$_CONNECFAIL | Programming error, INET management error, or hardware error. The connection was abnormally terminated.
> SS$_DEVINACT | INET management error. The driver has not been started. You must execute a UCX START COMMUNICATION command before issuing a $QIO routine.
> SS$_DEVNOTMOUNT | INET management error. You improperly executed the INET startup procedure. The driver was loaded, but the INET_ACP was not activated.
> SS$_INSFMEM | INET management or programming error. There is not enough buffer space for allocation. The INET software needs more buffer space. You should set a higher quota for the dynamic buffer space, or shut down and restart your internet with a larger static buffer space.
> SS$_IVBUFLEN | Programming error occurred for one of the following reasons: The size of the buffer for an I/O function is insufficient. You tried to issue an IO$_READVBLK or IO$_WRITEVBLK that specifies a correct buffer address ( p1 valid), but does not specify a buffer length ( p2 is null).
> SS$_LINKDISCON | A virtual circuit (TCP/IP) was closed at the initiative of the peer.
> SS$_NOLINKS | Programming error. Read attempt on unconnected TCP socket.
> SS$_SHUT | The network is being shut down.
> SS$_SUSPENDED | The operation is blocked for one of the following reasons: No messages were received so the receive operation cannot complete. The socket is marked as nonblocking. The socket has the OOBINLINE option clear, and the OOB character has already been read.
> SS$_TIMEOUT | This applies to a socket that has KEEPALIVE set. The connection was idle for longer than the timeout interval (10 minutes is the default).
> SS$_UNREACHABLE | Communication status. The remote host or network is unreachable.

Example 4-9 IO$_READVBLK Function (MACRO-32 Programming)

            .title Read_v
    ;+
    ;       Read using a vectored buffer descriptor
    ;-
            .ident  /01/

            $inetsymdef             ; INET symbols

    dev:    .ascid  /ucx$device:/           ; INET device name
    channel:        .word   0       ; INET channel
    iostatus:       .quad   0       ; I/O status block
    Ret_adr:        .blkb 16        ; Buffer for remote host IP address
    Ret_len=.-Ret_adr
    leng:   .long   0               ; Return length of Remote IP address
    loc_adr:.word   INET$C_AF_INET  ; INET family
            .word   5001            ; Port number
                                    ; Local host IP address
            .byte   128,20,20       ; Network/subnetwork number
            .byte   10              ; Host number
            .blkb   8
    par11:  .word   INET$C_UDP      ; UDP/IP  protocol
            .word   INET_PROTYP$C_DGRAM  ; Datagram type of socket
    ;
    ; Item_list_3 descriptor for the Remote IP address
    ;
    par12:  .long   ret_len         ; Length
            .address ret_adr        ; Buffer address
            .address leng           ; Returned length
    ;
    ; Item_list_2 descriptor for the Local IP address
    ;
    par13:  .long   ret_len         ; Length
            .address loc_adr        ; Address
    ;
    ; I/O Buffer
    ;
    buffer_1:
            .blkb   512
    buflen=.-buffer_1
    buffer_2:
            .blkb   512
    buffer_3:
            .blkb   512
    buffer_4:
            .blkb   512
    buf_d:  .long   len_d
            .address buffer_d
    buffer_d:
            .long   buflen
            .address buffer_1
            .long   buflen
            .address buffer_2
            .long   buflen
            .address buffer_3
            .long   buflen
            .address buffer_4
    len_d=.-buffer_d

            .entry   start,^m<>
    ;
    ;       Assign an INET  device
    ;
            $assign_s       devnam=dev, chan=channel
            blbs    r0,read
            brw     exit
    ;
    ; Create and bind the device socket to the local host
    ;
    read:
            $qioW_s efn=#31,-               ; Event flag
                    chan=channel, -         ; Channel
                    func=#io$_setmode,-     ; I/O Function
                    iosb= iostatus, -       ; I/O status block
                    p1=par11,-              ; Socket creation parameters
                    P3=#Par13               ; Socket Bind parameters
            blbc    r0,exit
    ;
    ; Perform a QIOW read operation
    ;
            $qiow_s efn=#31,-               ; Event flag
                    chan=channel, -         ; Channel
                    func=#io$_readvblk,-    ; I/O function
                    iosb= iostatus,-        ; I/O status
                    p3=#par12,-; Descriptor of the remote Host IP address
                    P6=#buf_d               ; Vectored buffer descriptor
    exit:
            ret                             ; Exit

            .end start

Example 4-10 IO$_READVBLK Function --- Vectored Buffers (C Programming)

    #module read_vecio
    /*
    **++
    **
    ** This example does vectored buffers read
    **
    **--
    */

    /*
    **  INCLUDE FILES
    */

    #include <descrip.h>
    #include <ucx$inetdef.h>     /* INET symbol definitions */
    #include <iodef.h>

    /*
    **
    */

    struct bvec              /* Structure definition for vec buf */
              {
                int length ;
                char *b_adrs ;
              } ;

    struct sockaddr {          /* Structure definition for socket adrs */
            short inet_family ;
            short inet_port ;
            char adrs[4] ;
            char blkb[8] ;
           } ;

    main()

    {
         int status ;          /* For return status */
         short channel ;       /* INET channel */
         short sck_parm[2] ;  /* Socket creation parameter */
         char buf_1[12],buf_2[12],buf_3[12],buf_4[12] ;
         struct sockaddr remote_host ; /Socket adrs definition for rhst */
         struct sockaddr local_host ; /Socket adrs definition for lhst */
         struct itlst lhst_adrs ;
         struct itlst rhst_adrs ;
         struct bvec buf_vec[5] =
              {
              {12, &buf_1 },
              {12, &buf_2 },
              {12, &buf_3 },
              {12, &buf_4 },
              {0, 0 }
              } ;

    /* Descriptor for Inet device name */

         struct dsc$descriptor dev =
             { 11, DSC$K_CLASS_S, DSC$K_DTYPE_T, "UCX$DEVICE:"} ;

    /* Descriptor for vectored buffer */

         struct desc$descriptor buf_d =
             { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0} ;

    /* Initialize the parameters */

            sck_parm[0] = INET$C_UDP ;     /* UDP/IP protocol */
            sck_parm[1] = INET_PROTYP$C_DGRAM ; /*Datagram type of socket*/

    /* Itlst for local IP address */

            lhst_adrs.lgth = sizeof(local_host);
            lhst_adrs.hst = &local_host ;

            rhst_adrs.lgth = sizeof(remote_host) ;
            rhst_adrs.hst = &remote_host ;

            buf_d.dsc$a_pointer = buf_vec;
            buf_d.dsc$w_length = sizeof(bvec) ;

    /* Initialize socket address for remote host */

           remote_host.inet_family = INET$C_AF_INET ; /* INET family */
           remote_host.inet_port = 5002 ;        /* Port number */
           remote_host.adrs[0] = 128 ;           /* Network/subnetwork*/
           remote_host.adrs[0] = 20 ;            /*  number */
           remote_host.adrs[0] = 20 ;
           remote_host.adrs[0] = 156 ;             /* Host number */
           remote_host.blkb[0] = 0 ;
           remote_host.blkb[1] = 0 ;
           remote_host.blkb[2] = 0 ;
           remote_host.blkb[3] = 0 ;
           remote_host.blkb[4] = 0 ;
           remote_host.blkb[5] = 0 ;
           remote_host.blkb[6] = 0 ;
           remote_host.blkb[7] = 0 ;

    /* Initialize socket address for local host */

           local_host.inet_family = AF_INET ;     /* INET family */
           local_host.inet_port = 5002 ;          /* Port number */
           local_host.adrs[0] = 128 ;             /* Network/subnetwork*/
           local_host.adrs[0] = 20 ;              /*  number */
           local_host.adrs[0] = 20 ;
           local_host.adrs[0] = 156 ;             /* Host number */
           local_host.blkb[0] = 0 ;
           local_host.blkb[1] = 0 ;
           local_host.blkb[2] = 0 ;
           local_host.blkb[3] = 0 ;
           local_host.blkb[4] = 0 ;
           local_host.blkb[5] = 0 ;
           local_host.blkb[6] = 0 ;
           local_host.blkb[7] = 0 ;

    /*
    ** Assign a channel to INET device
    */

            status = SYS$ASSIGN( &dev,
                                 &channel,
                                 0,
                                 0) ;
             if ((status & 1) == 0) {
                printf("Failed to assign channel to INET device \n") ;
                return(status) ;
                 }

    /*
    ** Create and bind the device socket to local host
    */

            status = SYS$QIOW( 31,          /* Event flag */
                               channel,    /* Channel number */
                               IO$_SETMODE, /* I/O function */
                               iosb,        /* I/O status block */
                               0,
                               0,
                               &sck_parm, /* P1 Socket creation parameter */
                               0,
                               &lhst_adrs, /* P3 Socket bind parameter */
                               0,0,0) ;
            if ((status & 1) == 0) {
                printf("Failed to create and bind the devicesocket \n") ;
                return(status) ;

    /*
    ** Perform the QIO read operation
    */

         status = SYS$QIOW( 31,          /* Event flag */
                            channel,    /* Channel number */
                            IO$_READVBLK,/* I/O function */
                            iosb,        /* I/O status block */
                            0,
                            0,
                            0,
                            0,
                            &rhst_adrs,  /* P3 Remote host adrs desc */
                            0,
                            0,
                            &buf_d) ;   /* P6 Vectored buffer desc */
         if ((status & 1) == 0) {
             printf("Failed to read from  device \n") ;
             return(status) ;
         }

    /*
    ** Deassign the INET dev channel
    */
            SYS$DASSGN (channel);

            return(status) ;
    }

Example 4-11 IO$_READVBLK Function --- INET device (C Programming)

    #module read_io
    /*
    **++
    **
    ** This example does read from INET device
    **
    **--
    */

    /*
    **  INCLUDE FILES
    */

    #include <descrip.h>
    #include <ucx$inetdef.h>     /* INET symbol definitions */
    #include <iodef.h>

    struct sockaddr {            /* Structure definition for socket adrs */
            short inet_family ;
            short inet_port ;
            char adrs[4] ;
            char blkb[8] ;
           } ;

    struct itlst {
            int lgth ;
            struct sockaddr *hst ;
             } ;
    main()

    {
         int status ;            /* For return status */
         short channel           /* INET channel */
         short sck_parm[2] ;     /* Socket creation parameter */
         int iosb [2] ;          /* I/O status block           */
         struct sockaddr local_host ; /* Socket adrs definition for lhst */
         struct itlst lhst_adrs ;
         char buf[128] ;
         int buflen = 128 ;

    /* Descriptor for Inet device name */

         struct dsc$descriptor dev =
             { 3, DSC$K_CLASS_S, DSC$K_DTYPE_T, "UCX$DEVICE:"} ;

    /* Initialize the parameters */

         sck_parm[0] = INET$C_UDP ;     /* UDP/IP protocol */
         sck_parm[1] = INET_PROTYP$C_DGRAM ; /* Datagram type of socket */

    /* Itlst for local IP address */

         lhst_adrs.lgth = sizeof(local_host);
         lhst_adrs.hst = &local_host ;
    /*
    ** Assign a channel to INET device
    */

            status = SYS$ASSIGN( &dev,
                                 &channel,
                                 0,
                                 0) ;
          if ((status & 1) == 0) {
             printf("Failed to assign channel to INET device \n") ;
             return(status) ;
              }
    /* Initialize socket address for local host */

           local_host.inet_family = INET$C_AF_INET ;/* INET family */
           local_host.inet_port = 0 ;             /* Port number */
           local_host.adrs[0] = 128 ;             /* Network/subnetwork*/
           local_host.adrs[1] = 45 ;              /*  number */
           local_host.adrs[2] = 45 ;
           local_host.adrs[3] = 216 ;               /* Host number */
           local_host.blkb[0] = 0 ;
           local_host.blkb[1] = 0 ;
           local_host.blkb[2] = 0 ;
           local_host.blkb[3] = 0 ;
           local_host.blkb[4] = 0 ;
           local_host.blkb[5] = 0 ;
           local_host.blkb[6] = 0 ;
           local_host.blkb[7] = 0 ;
    /*
    ** Create and bind the device socket to local host
    */

         status = SYS$QIOW( 31,          /* Event flag */
                            channel,     /* Channel number */
                            IO$_SETMODE, /* I/O function */
                            iosb,        /* I/O status block */
                            0,
                            0,
                            &sck_parm, /* P1 Socket creation parameter */
                            0,
                            &lhst_adrs, /* P3 Socket bind parameter */
                            0,0,0) ;
         if ((status & 1) == 0) {
             printf("Failed to create and bind the device socket \n") ;
             return(status) ;
           }
    /*
    ** Perform the QIO read operation
    */

         status = SYS$QIOW( 0,           /* Event flag */
                            channel,    /* 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) == 0) {
             printf("Failed to read from inet device \n") ;
             return(status) ;
         }
    /*
    ** Deassign the INET dev channel
    */
            SYS$DASSGN (channel);

            return(status) ;

    }

# IO$_SENSEMODE/IO$_SENSECHAR

> The Sense Mode (IO$_SENSEMODE) and Sense Characteristics (IO$_SENSECHAR) I/O functions return the characteristics of the internet pseudodevice.

Previous | Next | Contents