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