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

Previous | Contents | Index

The `recv()` function receives data from a connected socket and places it in a buffer, as follows:

1. `conn_sockfd` is the socket descriptor created as a result of a call to the `accept()` function.
2. `buf` points to the buffer into which received data is placed.
3. `1` indicates the size of the buffer.
4. `MSG_PEEK` is the flag that specifies the character entered is looked at without removing it from the buffer.

## 2.12.2 Peeking at Data (System Services)

To peek at data that is next in the socket receive queue, use the IO$_READVBLK function of the $QIO system service and use the TCPIP$C_MSG_PEEK flag. This allows you to use multiple read operations on the same data.

# 2.13 Writing Data

For programs that use TCP, data writing occurs after a client program initiates a connection and after the server program accepts the connection. When using UDP, you also have the option of establishing a default peer address with a specific socket, but this is not required for data transfer.

## 2.13.1 Writing Data (Sockets API)

Example 2-20 shows a TCP server using the `send()` function to transmit data.

Example 2-20 Writing Data (Sockets API)

    #include <in.h>                     /* define internet related constants,   */
                                        /* functions, and structures            */
    #include <inet.h>                   /* define network address info          */
    #include <netdb.h>                  /* define network database library info */
    #include <socket.h>                 /* define BSD socket api                */
    #include <stdio.h>                  /* define standard i/o functions        */
    #include <stdlib.h>                 /* define standard library functions    */
    #include <string.h>                 /* define string handling functions     */

    #define SERV_BACKLOG    1               /* server backlog                   */
    #define SERV_PORTNUM    12345           /* server port number               */

    int main( void )
    {
        int optval = 1;                     /* SO_REUSEADDR's option value (on) */

        int conn_sockfd;                    /* connection socket descriptor     */
        int listen_sockfd;                  /* listen socket descriptor         */

        unsigned int cli_addrlen;           /* returned length of client socket */
                                            /* address structure                */
        struct sockaddr_in cli_addr;        /* client socket address structure  */
        struct sockaddr_in serv_addr;       /* server socket address structure  */

        char buf[] = "Hello, world!";       /* data buffer                      */

        /*
         * initialize server's socket address structure
         */

        memset( &serv_addr, 0, sizeof(serv_addr) );
        serv_addr.sin_family      = AF_INET;
        serv_addr.sin_port        = htons( SERV_PORTNUM );
        serv_addr.sin_addr.s_addr = INADDR_ANY;

        /*
         * create a listen socket
         */

        if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
            {
            perror( "Failed to create socket" );
            exit( EXIT_FAILURE );
            }
        /*
         * bind server's ip address and port number to listen socket
         */

        if ( setsockopt(listen_sockfd,
                        SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0 )
            {
            perror( "Failed to set socket option" );
            exit( EXIT_FAILURE );
            }

        if ( bind(listen_sockfd,
                  (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
            {
            perror( "Failed to bind socket" );
            exit( EXIT_FAILURE );
            }
        /*
         * set socket as a listen socket
         */

        if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
            {
            perror( "Failed to set socket passive" );
            exit( EXIT_FAILURE );
            }

        /*
         * accept connection from a client
         */

        printf( "Waiting for a client connection on port: %d\n",
                ntohs(serv_addr.sin_port)
              );

        conn_sockfd = accept( listen_sockfd, (struct sockaddr *) 0, 0 );

        if ( conn_sockfd < 0 )
            {
            perror( "Failed to accept client connection" );
            exit( EXIT_FAILURE );
            }

        /*
         * log client connection request
         */

        cli_addrlen = sizeof(cli_addr);
        memset( &cli_addr, 0, sizeof(cli_addr) );

        if ( getpeername(conn_sockfd,
                         (struct sockaddr *) &cli_addr, &cli_addrlen) < 0 )
            {
            perror( "Failed to get client name" );
            exit( EXIT_FAILURE );
            }

        printf( "Accepted connection from host: %s, port: %d\n",
                inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)
              );

        /*
         * write data to connection
         */
        if ( send(conn_sockfd, (1)
     buf, (2)
     sizeof(buf),(3)
     0 (4)
    ) < 0 )
            {
            perror( "Failed to write data to connection" );
            exit( EXIT_FAILURE );
            }

        printf( "Data sent: %s\n", buf );

        exit( EXIT_SUCCESS );
    }

1. `conn_sockfd` specifies the connected socket that is to receive the data.
2. `buf` is the address of the send buffer where the data to be sent is placed.
3. `sizeof (buf)` indicates the size of the send buffer.
4. `flag` , when set to 0, indicates that OOB data is not being sent.

## 2.13.2 Writing Data (System Services)

The IO$_WRITEVBLK function of the $QIO system service copies data from the address space of the user's process to system dynamic memory and then transfers the data to an internet host or port.

Example 2-21 shows a TCP server using the IO$_WRITEVBLK function to transmit a single data buffer. The $QIO(IO$_ACCESS|IO$M_ACCEPT) function was previously executed to establish the connection with the client.

Example 2-21 Writing Data (System Services)

    #include <descrip.h>                /* define OpenVMS descriptors           */
    #include <efndef.h>                 /* define 'EFN$C_ENF' event flag        */
    #include <in.h>                     /* define internet related constants,   */
                                        /* functions, and structures            */
    #include <inet.h>                   /* define network address info          */
    #include <iodef.h>                  /* define i/o function codes            */
    #include <netdb.h>                  /* define network database library info */
    #include <ssdef.h>                  /* define system service status codes   */
    #include <starlet.h>                /* define system service calls          */
    #include <stdio.h>                  /* define standard i/o functions        */
    #include <stdlib.h>                 /* define standard library functions    */
    #include <string.h>                 /* define string handling functions     */
    #include <stsdef.h>                 /* define condition value fields        */
    #include <tcpip$inetdef.h>          /* define tcp/ip network constants,     */
                                        /* structures, and functions            */

    #define SERV_BACKLOG    1               /* server backlog                   */
    #define SERV_PORTNUM    12345           /* server port number               */

    struct iosb
        {                                   /* i/o status block                 */
        unsigned short status;              /* i/o completion status            */
        unsigned short bytcnt;              /* bytes transferred if read/write  */
        void *details;                      /* address of buffer or parameter   */
        };

    struct itemlst_2
        {                                   /* item-list 2 descriptor/element   */
        unsigned short length;              /* length                           */
        unsigned short type;                /* parameter type                   */
        void *address;                      /* address of item list             */
        };

    struct itemlst_3
        {                                   /* item-list 3 descriptor/element   */
        unsigned short length;              /* length                           */
        unsigned short type;                /* parameter type                   */
        void *address;                      /* address of item list             */
        unsigned int *retlen;               /* address of returned length       */
        };

    struct sockchar
        {                                   /* socket characteristics           */
        unsigned short prot;                /* protocol                         */
        unsigned char type;                 /* type                             */
        unsigned char af;                   /* address format                   */
        };

    int main( void )
    {
        int optval = 1;                     /* reuseaddr option value (on)      */

        struct iosb iosb;                   /* i/o status block                 */
        unsigned int status;                /* system service return status     */

        unsigned short conn_channel;        /* connect inet device i/o channel  */

        unsigned short listen_channel;      /* listen inet device i/o channel   */
        struct sockchar listen_sockchar;    /* listen socket characteristics    */

        unsigned int cli_addrlen;           /* returned length of client socket */
                                            /* address structure                */
        struct sockaddr_in cli_addr;        /* client socket address structure  */
        struct itemlst_3 cli_itemlst;       /* client socket address item-list  */

        struct sockaddr_in serv_addr;       /* server socket address structure  */
        struct itemlst_2 serv_itemlst;      /* server socket address item-list  */

        struct itemlst_2 sockopt_itemlst;   /* server socket option item-list   */
        struct itemlst_2 reuseaddr_itemlst; /* reuseaddr option item-list       */
        char buf[] = "Hello, world!";       /* data buffer                      */
        int buflen = sizeof( buf );         /* length of data buffer            */

        $DESCRIPTOR( inet_device,           /* string descriptor with logical   */
                     "TCPIP$DEVICE:" );     /* name of network pseudodevice     */

        /*
         * initialize socket characteristics
         */

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

        /*
         * initialize reuseaddr's item-list element
         */

        reuseaddr_itemlst.length  = sizeof( optval );
        reuseaddr_itemlst.type    = TCPIP$C_REUSEADDR;
        reuseaddr_itemlst.address = &optval;

        /*
         * initialize setsockopt's item-list descriptor
         */

        sockopt_itemlst.length  = sizeof( reuseaddr_itemlst );
        sockopt_itemlst.type    = TCPIP$C_SOCKOPT;
        sockopt_itemlst.address = &reuseaddr_itemlst;

        /*
         * initialize client's item-list descriptor
         */

        cli_itemlst.length  = sizeof( cli_addr );
        cli_itemlst.type    = TCPIP$C_SOCK_NAME;
        cli_itemlst.address = &cli_addr;
        cli_itemlst.retlen  = &cli_addrlen;

        /*
         * initialize server's item-list descriptor
         */

        serv_itemlst.length  = sizeof( serv_addr );
        serv_itemlst.type    = TCPIP$C_SOCK_NAME;
        serv_itemlst.address = &serv_addr;

        /*
         * initialize server's socket address structure
         */

        memset( &serv_addr, 0, sizeof(serv_addr) );
        serv_addr.sin_family      = TCPIP$C_AF_INET;
        serv_addr.sin_port        = htons( SERV_PORTNUM );
        serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;
        /*
         * assign i/o channels to network device
         */

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

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

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

        /*
         * create a listen socket
         */

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

        /*
         * bind server's ip address and port number to listen socket
         */
        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           listen_channel,      /* i/o channel                  */
                           IO$_SETMODE,         /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           0,                   /* p3                           */
                           0,                   /* p4                           */
                           &sockopt_itemlst,    /* p5 - socket options          */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to set socket option\n" );
            exit( status );
            }

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           listen_channel,      /* i/o channel                  */
                           IO$_SETMODE,         /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           &serv_itemlst,       /* p3 - local socket name       */
                           0,                   /* p4                           */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to bind socket\n" );
            exit( status );
            }

        /*
         * set socket as a listen socket
         */
        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           listen_channel,      /* i/o channel                  */
                           IO$_SETMODE,         /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           0,                   /* p3                           */
                           SERV_BACKLOG,        /* p4 - connection backlog      */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to set socket passive\n" );
            exit( status );
            }

        /*
         * accept connection from a client
         */

        printf( "Waiting for a client connection on port: %d\n",
                ntohs(serv_addr.sin_port)
              );

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           listen_channel,      /* i/o channel                  */
                           IO$_ACCESS|IO$M_ACCEPT,
                                                /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           0,                   /* p3                           */
                           &conn_channel,       /* p4 - i/o channel for new     */
                                                /*      connection              */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to accept client connection\n" );
            exit( status );
            }
        /*
         * log client connection request
         */

        memset( &cli_addr, 0, sizeof(cli_addr) );

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           conn_channel,        /* i/o channel                  */
                           IO$_SENSEMODE,       /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           0,                   /* p1                           */
                           0,                   /* p2                           */
                           0,                   /* p3                           */
                           &cli_itemlst,        /* p4 - peer socket name        */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;

        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to get client name\n" );
            exit( status );
            }

        printf( "Accepted connection from host: %s, port: %d\n",
                inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)
              );

        /*
         * write data to connection
         */

        status = sys$qiow( EFN$C_ENF,           /* event flag                   */
                           conn_channel,        /* i/o channel                  */
                           IO$_WRITEVBLK,       /* i/o function code            */
                           &iosb,               /* i/o status block             */
                           0,                   /* ast service routine          */
                           0,                   /* ast parameter                */
                           buf,                 /* p1 - buffer address          */
                           buflen,              /* p2 - buffer length           */
                           0,                   /* p3                           */
                           0,                   /* p4                           */
                           0,                   /* p5                           */
                           0                    /* p6                           */
                         );

        if ( status & STS$M_SUCCESS )
            status = iosb.status;
        if ( !(status & STS$M_SUCCESS) )
            {
            printf( "Failed to write data to connection\n" );
            exit( status );
            }

        printf( "Data sent: %s\n", buf );

        exit( EXIT_SUCCESS );
    }

You can also specify a list of write buffers by omitting the p1 and p2 parameters and instead passing the list of buffers as the p5 parameter. Note that, when writing a list of buffers, the p5 parameter is used; when reading a list, the p6 parameter is used. For more information, see Section 5.5.1.

# 2.14 Writing OOB Data (TCP Protocol)

If your application uses TCP, you can send OOB data to a remote process. At the remote process, the message is delivered to the user through either the data receive or the out-of-band data receive mechanism. You can write only 1 byte of OOB data at a time.

## 2.14.1 Writing OOB Data (Sockets API)

To send OOB data to a remote process, use the MSG_OOB flag with the `send()` , `sendmsg()` , and `sendto()` functions.

Example 2-22 shows a TCP server using the MSG_OOB flag with the `send()` function.

Example 2-22 Writing OOB Data (Sockets API)

    /* 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 123
    main() {
       struct sockaddr_in lcladdr;
       int r, s, one = 1;
       char *message = "Hello, world!\r\n",
            *oob_message = "\007";
       memset()

       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()` function is used to send OOB data to a remote socket, as follows:

Previous | Next | Contents | Index