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


Previous Contents Index

2.13.2 Writing Data with the C Socket Interface

Example 2-21 shows a TCP/IP client using the send() routine to transmit data.

Example 2-21 Writing Data Using C Socket Programming

#include  <errno.h> 
#include  <types.h> 
#include  <stdio.h> 
#include  <socket.h> 
#include  <in.h> 
#include  <netdb.h>      
#include  <inet.h> 
#include  <tcpip$inetdef.h>     /* INET symbol definitions */ 
#else 
   .
   .
   .
 
main(argc,argv) 
int  argc; 
char **argv; 
{ 
 
        int     sock_1;                      /* socket */ 
static  char   message[] = "Hi there."; 
static    struct  sockaddr_in sock2_name;         /* Address struct for socket2 
        struct  hostent         hostentstruct;  /* Storage for hostent data. 
 
        struct  hostent         *hostentptr;    /* Pointer to hostent data.  
 
        static  char            hostname[256];  /* Name of local host.       
 
     int  flag; 
     int  retval;                  /* helpful for debugging */ 
     int  shut = FALSE;            /* flag to cleanup */ 
      
        /* 
         * Send message to socket 2. 
         */ 
        flag = 0;        /* maybe 0 or MSG_OOB */ 
        retval = send(sock_1,(1)
        message,(2) sizeof (message),(3) flag);(4)
        if (retval < 0) 
                { 
                perror ("oob_messsend"); 
                shut = TRUE;        
                } 
 

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

2.14 Writing OOB Data (TCP)

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 the data receive, or out-of-band data receive mechanisms. You can write only one byte of OOB data at a time.

2.14.1 Writing OOB Data with OpenVMS System Services

To send out-of-band data to a remote process, issue a $QIO system service using the IO$_WRITEVBLK function with the IO$M_INTERRUPT modifier. Example 2-22 shows a TCP server using the MSG_OOB flag with the send() routine.

Example 2-22 Writing OOB Data Using OpenVMS System Services

/* 
** 
**  Attempt to send Out Of Band data to a previously established network 
**  connection. Use the function code of IO$_WRITEVBLK, passing the address 
**  of the buffer to P1, and the OOB code, TCPIP$C_MSG_OOB, to P4. 
** 
*/ 
    OOBBuff = 7; 
    sysSrvSts = sys$qiow( 0,              /* efn.v | 0 */ 
                          IOChannel,      /* chan.v */ 
                          IO$_WRITEVBLK,  /* func.v */ 
                          &iosb,          /* iosb.r | 0 */ 
                          0, 0,           /* astadr, astprm: UNUSED */ 
                          &OOBBuff,       /* p1.r IO buffer  */ 
                          1,              /* p2.v IO buffer  size */ 
                          0,              /* p3 UNUSED */ 
                          TCPIP$C_MSG_OOB,  /* p4.v IO options flag */ 
                          0, 0            /* p5, p6 UNUSED */   ); 
 
    if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */ 
       ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */ 
        { 
        cleanup( IOChannel ); 
        errorExit( sysSrvSts, iosb.cond_value ); 
        } 
    else 
        if( iosb.count == 0 ) 
            printf( "    FAILED to send the OOB message, no connection.\n" ); 
        else 
            printf( "    SUCCEEDED in sending the OOB message.\n" ); 
 

2.14.2 Writing OOB Data with the C Socket Interface

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

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

Example 2-23 Writing OOB Data Using C Socket Programming

/* This program accepts a connection on TCP port 1234, sends the string, 
   "Hello, world!", waits two seconds, sends an urgent BEL (^G), waits 
   another two seconds, repeats the Hello message, and terminates. */ 
 
#include <types.h> 
#include <in.h> 
#include <socket.h> 
#include <unixio.h> 
 
#define PORTNUM 1234 
 
main() { 
   struct sockaddr_in lcladdr; 
   int r, s, one = 1; 
   char *message = "Hello, world!\r\n", 
        *oob_message = "\007"; 
   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() routine is used to send OOB data to a remote socket, as follows:

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

2.15 Sending Datagrams (UDP)

An application that uses UDP can send a datagram to a remote host, send broadcast datagrams to multiple remote hosts, or send multicast datagrams to members of a group.

With broadcasting, you send datagrams in one operation to multiple remote hosts on the specified subnetwork. With multicasting, you send datagrams in one operation to all hosts that are members of a particular group. The member hosts can be located on the local network or on remote networks, as long as the routers are configured to support multicasting.

2.15.1 Sending Datagrams with OpenVMS System Services

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

2.15.2 Sending Broadcast Datagrams with OpenVMS System Services

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

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

2.15.3 Sending Broadcast Datagrams with the C Socket Interface

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

2.15.4 Sending Multicast Datagrams

To send IP multicast datagrams, specify the IP destination address in the range of 224.0.0.0 to 239.255.255.255 using the $QIO(IO$_WRITEVBLK) system service routine or the sendto() C Socket routine. Make sure you include the <netinet/in.h> header file.

The system maps the specified IP destination address to the appropriate Ethernet or FDDI multicast address prior to transmitting the datagram.

You can control multicast options by specifying the following arguments to the setsockopt() system call, as appropriate:

2.16 Closing and Deleting a Socket

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

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

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

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

2.16.1 Closing and Deleting with OpenVMS System Services

Make the following calls to close and delete a socket:

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

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

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

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

2.16.2 Closing and Deleting with the C Socket Interface

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

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

#include  <errno.h> 
#include  <types.h> 
#include  <stdio.h> 
#include  <socket.h> 
#include  <in.h> 
#include  <netdb.h>     
#include  <inet.h> 
   .
   .
   .
main(argc,argv) 
int  argc; 
char **argv; 
{ 
 
        int     sock_1;                         /* socket */ 
static  char   message[] = "Hi there."; 
static  struct  sockaddr_in sock2_name;         /* Address struct for socket2*/ 
        struct  hostent         hostentstruct;  /* Storage for hostent data. */ 
        struct  hostent         *hostentptr;    /* Pointer to hostent data.  */ 
        static  char            hostname[256];  /* Name of local host.       */ 
     int  flag; 
     int  retval;                  /* helpful for debugging */ 
     int  shut = FALSE;            /* flag to cleanup */ 
                                                
     /* 
      * Close socket. 
      */ 
     retval = close (sock_1);(1)
     if (retval) 
             perror ("close"); 
 
     exit(); 
 
} 
 

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

2.17 Shutting Down Sockets

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

2.17.1 Shutting Down a Socket with OpenVMS System Services

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

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

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

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

/* 
** 
** Shutdown this server. 
** 
*/ 
    sysSrvSts = sys$qiow( 0,                 /* efn.v | 0 */ 
                          IOChannel,         /* chan.v */ 
                          IO$_DEACCESS | 
                              IO$M_SHUTDOWN, /* func.v */ 
                          &iosb,             /* iosb.r | 0 */ 
                          0, 0,              /* astadr, astprm: UNUSED */ 
                          0, 0, 0,           /* p1, p2, p3 UNUSED */ 
                          TCPIP$C_DSC_ALL,   /* p4.v mode to shutdown */ 
                          0, 0               /* p5, p6 UNUSED */   ); 
 
    if((( sysSrvSts & 1  ) != 1 ) || /* Validate the system service status. */ 
       ((  iosb.cond_value & 1  ) != 1))  /* Validate the IO status. */ 
        errorExit( sysSrvSts, iosb.cond_value ); 
    else 
        printf( "    SUCCEEDED in shutting down this server.\n" ); 
 
    sys$dassgn( IOChannel ); 
                

2.17.2 Shutting Down with a C Socket Interface

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

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

#include  <errno.h> 
#include  <types.h> 
#include  <stdio.h> 
#include  <socket.h> 
#include  <in.h> 
#include  <netdb.h>      
#include  <inet.h> 
#include  <tcpip$inetdef.h>     /* INET symbol definitions */ 
   .
   .
   .
 
        /* 
         * Call cleanup to shutdown and close socket. 
         */           
        cleanup(sock_1); 
 
 } /* end main */ 
 
 
/*-----------------------------------------------------------*/ 
 
cleanup(socket) 
int        socket; 
        
{ 
        int        retval; 
 
        /* 
         * Shutdown socket  completely. 
         */ 
        retval = shutdown(socket(1),3)(2); 
        if (retval == -1) 
                perror ("shutdown"); 
 
 
 
        /* 
         * Close socket. 
         */ 
        retval = close (socket); 
        if (retval) 
                perror ("close"); 
 
        exit(); 
 
} /* end cleanup */ 

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

2.18 Canceling I/O Operations

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

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

2.19 Application Development Tools for OpenVMS System Services Programming

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

2.19.1 Include Files for OpenVMS System Services Programming

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

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


Previous Next Contents Index