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

Previous | Contents | Index

## 2.17.2 Closing and Deleting (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 network device and deassigns the I/O channel previously acquired with the $ASSIGN service.

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

Example 2-27 Closing and Deleting a Socket (System Services)

    #include <descrip.h>                /* define OpenVMS descriptors           */
    #include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */
    #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 <stsdef.h>                 /* define condition value fields        */
    #include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */
                                        /* structures, and functions            */

    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 sockchar
        {                                   /* socket characteristics           */
        unsigned short prot;                /* protocol                         */
        unsigned char type;                 /* type                             */
        unsigned char af;                   /* address format                   */
        };

    int main( void )
    {
        struct iosb iosb;                   /* i/o status block                 */
        unsigned int status;                /* system service return status     */
        unsigned short channel;             /* network device i/o channel       */
        struct sockchar sockchar;           /* socket characteristics buffer    */
        $DESCRIPTOR( inet_device,           /* string descriptor with logical   */
                     "TCPIP$DEVICE:" );     /* name of network pseudodevice     */

        /*
         * initialize socket characteristics
         */

        sockchar.prot = TCPIP$C_TCP;
        sockchar.type = TCPIP$C_STREAM;
        sockchar.af   = TCPIP$C_AF_INET;

        /*
         * assign i/o channel to network device
         */

        status = sys$assign( &inet_device,      /* device name                  */
                             &channel,          /* i/o channel                  */
                             0,                 /* access mode                  */
                             0                  /* not used                     */
                           );

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

        /*
         * create a socket
         */
        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           channel,             /* i/o channel                  */
                           IO$_SETMODE,         /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           &sockchar,           /* p1 - socket characteristics  */
                           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 );
            }

        /*
         * close socket
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           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 i/o channel to network device
         */

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

        exit( EXIT_SUCCESS );
    }

# 2.18 Shutting Down Sockets

You can shut down a socket before closing and deleting it. The shutdown operation allows you to shut down communication one process at a time. This maintains unidirectional rather than the normal bidirectional connections, allowing you to shut down communications on receive or transmit data queues, or both. 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.

## 2.18.1 Shutting Down a Socket (Sockets API)

Example 2-28 shows a TCP application using the `shutdown()` function.

Example 2-28 Shutting Down a Socket (Sockets API)

    #include <socket.h>                 /* define BSD socket api                */
    #include <stdio.h>                  /* define standard i/o functions        */
    #include <stdlib.h>                 /* define standard library functions    */
    #include <unixio.h>                 /* define unix i/o                      */

    int main( void )
    {
        int sockfd;

        /*
         * create a socket
         */

        if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
            {
            perror( "Failed to create socket" );
            exit( EXIT_FAILURE );
            }

        /*
         * shutdown a socket
         */

        if ( shutdown(sockfd,(1) 2 (2)) < 0 )
            {
            perror( "Failed to shutdown socket connections" );
            exit( EXIT_FAILURE );
            }

        /*
         * close socket
         */

        if ( close(sockfd) < 0 )
            {
            perror( "Failed to close socket" );
            exit( EXIT_FAILURE );
            }

        exit( EXIT_SUCCESS );
    }

1. `sockfd` specifies the socket descriptor for the socket being shut down.
   Other valid socket descriptor values are:
   - `1` closes the receive socket queue.
   - `3` closes both the transmit and receive socket queues.
   The `close()` function then closes the socket and deletes the socket descriptor.

## 2.18.2 Shutting Down a Socket (System Services)

To shut down a socket, use the IO$_DEACCESS function with the IO$M_SHUTDOWN function modifier. This function shuts down all or part of the full-duplex connection on the 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-29 shows a TCP server using the IO$_DEACCESS function with the IO$M_SHUTDOWN function modifier to shut down all communications. In this example, no data is received or transmitted and all queued data is discarded.

Example 2-29 Shutting Down a Socket (System Services)

    #include <descrip.h>                /* define OpenVMS descriptors           */
    #include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */
    #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 <stsdef.h>                 /* define condition value fields        */
    #include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */
                                        /* structures, and functions            */

    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 sockchar
        {                                   /* socket characteristics           */
        unsigned short prot;                /* protocol                         */
        unsigned char type;                 /* type                             */
        unsigned char af;                   /* address format                   */
        };

    int main( void )
    {
        struct iosb iosb;                   /* i/o status block                 */
        unsigned int status;                /* system service return status     */
        unsigned short channel;             /* network device i/o channel       */
        struct sockchar sockchar;           /* socket characteristics buffer    */
        $DESCRIPTOR( inet_device,           /* string descriptor with logical   */
                     "TCPIP$DEVICE:" );     /* name of network pseudodevice     */

        /*
         * initialize socket characteristics
         */

        sockchar.prot = TCPIP$C_TCP;
        sockchar.type = TCPIP$C_STREAM;
        sockchar.af   = TCPIP$C_AF_INET;

        /*
         * assign i/o channel to network device
         */

        status = sys$assign( &inet_device,      /* device name                  */
                             &channel,          /* i/o channel                  */
                             0,                 /* access mode                  */
                             0                  /* not used                     */
                           );

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

        /*
         * create a socket
         */
        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           channel,             /* i/o channel                  */
                           IO$_SETMODE,         /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           &sockchar,           /* p1 - socket characteristics  */
                           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 );
            }

        /*
         * shutdown a socket
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           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 socket connections\n" );
            exit( status );
            }

        /*
         * close socket
         */
        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           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 i/o channel to network device
         */

        status = sys$dassgn( channel );

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

        exit( EXIT_SUCCESS );
    }

# 2.19 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 Sockets API function for this operation; the Sockets API library functions are synchronous.

# Chapter 3
Using the Sockets API

This chapter contains information to help you increase the portability of the network application programs that you write using the TCP/IP Services implementation of the Sockets API.

# 3.1 Internet Protocols

The IP (Internet Protocol) family is a collection of protocols on the Transport layer that use the internet address format. This section describes TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) sockets.

## 3.1.1 TCP Sockets

TCP provides reliable, flow-controlled, two-way transmission of data. A byte-stream protocol used to support the `SOCK_STREAM` abstraction, TCP uses the standard IP address format and provides a per-host collection of port addresses. Thus, each address consists of an internet address specifying the host and network, with a specific TCP port on the host identifying the peer entity.

Sockets using TCP are either active or passive, as described in Table 3-1.

Active sockets use the `connect()` function to initiate connections.)

Table 3-1 TCP Socket Types
Socket Type | Description
--- | ---
Active | Initiates connections to passive sockets. By default, TCP sockets are active.
Passive | Listens for connection requests from active sockets. To create a passive socket, use the `bind()` function and then the `listen()` function. Passive sockets use the `accept()` function to accept incoming connections. If the server is running on a multihomed system, you can specify wildcard addressing. Wildcard addressing allows a single server to provide service to clients on multiple networks. (See Section 3.1.1.1.)

### 3.1.1.1 Wildcard Addressing

When a server is running on a host that has more than one network interface installed, you can use wildcard addressing to configure it to accept incoming connections on all the interfaces.

The wildcard address is the any-interface choice. You specify this address by setting the IP address in the socket address structure to `INADDR_ANY` before calling the `bind()` function.

To create a socket that listens to all hosts on any network interface, perform these steps:

1. Bind the internet address `INADDR_ANY` .
2. Specify the TCP port.
   If you do not specify the port, the system assigns a unique port, starting at port number 49152. Once connected, the socket's address is fixed by the peer entity's location.

The address assigned to the socket is the address associated with the network interface through which packets from the peer are being transmitted and received. This address corresponds to the peer entity's network.

TCP supports the setting of socket options with the `setsockopt()` function and the checking of current option settings with the `getsockopt` function. Under most circumstances, TCP sends data when it is presented. When outstanding data has not been acknowledged, TCP gathers small amounts of output and sends it in a single packet when an acknowledgment is received.

For a small number of clients, such as window systems that send a stream of mouse events that receive no replies, this packetization can cause significant delays. Therefore, TCP provides a Boolean option, `TCP_NODELAY` (from TCP.H), to defeat this algorithm. The option level for the `setsockopt()` function is the protocol number for TCP, which is available from `getprotobyname()` . In this situation, servers may want to use `TCP_NODELAY` ; however, network traffic may increase significantly as a result.

## 3.1.2 UDP Sockets

UDP is a protocol that supports the `SOCK_DGRAM` abstraction for the internet protocol family. UDP sockets are connectionless and are normally used with the `sendto()` and `recvfrom()` functions. You can also use the `connect()` function to establish the destination address for future datagrams; then you use the `read()` , `write()` , `send()` , `rec()` , or `recv()` function to transmit or receive datagrams.

UDP address formats are identical to those used by TCP. In particular, UDP provides a port identifier in addition to the normal internet address format. Note that the UDP port space is separate from the TCP port space (for example, a UDP port cannot be connected to a TCP port). Also, you can send broadcast packets (assuming the underlying network supports this) by using a reserved broadcast address. This address is network-interface dependent. The `SO_BROADCAST` option must be set on the socket, and the process must have a privileged UIC or the SYSPRV, BYPASS, or OPER privilege for broadcasting to succeed.

# 3.2 Structures

This section describes, in alphabetical order, the structures you supply as arguments to the various Sockets API functions. Table 3-2 lists these structures.

Table 3-2 Structures for Sockets API
Structure | Description
--- | ---
`hostent` | This structure holds a canonical host name, alias names, a host address type, the length of the address, and a pointer to a list of host addresses. This structure is a parameter value for host name and address lookup functions.
`in_addr` | This structure holds a 32-bit IPv4 address stored in network byte order.
`iovec` | This structure holds the beginning address and length of an I/O buffer.
`linger` | This structure holds option information for the `close` function.
`msghdr` | This structure holds the protocol address, the size of the protocol address, a scatter-and-gather array, the number of elements in the scatter-and-gather array, ancillary data, the length of the ancillary data, and returned flags. The structure is a parameter of the `recvmsg()` and `sendmsg()` functions.
`netent` | This structure holds a network name, a list of aliases associated with the network, and the network number.
`sockaddr` | The socket functions use this generic socket address structure to function with any of the supported protocol families.
`sockaddr_in` | This IPv4 socket address structure holds the length of the structure, the address family, either a TCP or a UDP port number, and a 32-bit IPv4 address stored in network byte order. The structure has a fixed length of 16 bytes.
`timeval` | This structure holds a time interval specified in seconds and microseconds.

Previous | Next | Contents | Index