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


Previous Contents Index

  1. r specifies the remote socket descriptor connected to the local socket as a result of a call to the socket() function.
  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.14.2 Writing OOB Data (System Services)

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

Example 2-23 Writing OOB Data (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.15 Sending Datagrams (UDP Protocol)

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 (System Services)

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

2.15.2 Sending Broadcast Datagrams (Sockets API)

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

2.15.3 Sending Broadcast Datagrams (System Services)

To broadcast datagrams, use 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 the Compaq TCP/IP Services for OpenVMS Management guide.

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 function or the sendto() Sockets API function. Make sure you include the IN.H header file.

The system maps the specified IP destination address to the appropriate Ethernet or FDDI multicast address before it transmits the datagram.

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

2.16 Using the Berkeley Internet Name Domain Service

The Berkeley Internet Name Domain (BIND) service is a host name and address lookup service for the Internet. If BIND is enabled on your system, you can make a call to the BIND resolver to obtain host names and addresses.

Typically, you make a call to the BIND resolver either before you bind a socket or before you make a connection to a socket. You can also use this service to translate either the local or remote host name to an address before making a connection.

2.16.1 BIND Lookups (Sockets API)

If the BIND resolver is enabled on your system and the host name is not found in the local database, you can use either of the following functions to search the BIND database:

The host record contains both name and address information.

Example 2-24 shows how to use the gethostname() , gethostbyname() , and gethostbyaddr() functions to find a local host name and address.

Example 2-24 BIND Lookup (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 <stdio.h>                  /* define standard i/o functions        */ 
#include <stdlib.h>                 /* define standard library functions    */ 
 
int main( void ) 
{ 
    char host[1024]; 
    struct in_addr addr; 
    struct hostent *hptr; 
    /* 
     * get name of local host 
     */ 
    if ( (gethostname(host, sizeof(host))) < 0 )  (1)
        { 
        perror( "Failed to get host's local name" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    printf( "Local hostname: %s\n", host ); 
 
    /* 
     * lookup local host record by name 
     */ 
 
    if ( !(hptr = gethostbyname(host)) )   (2)
        { 
        perror( "Failed to find record for local host" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    addr.s_addr = *(int *) hptr->h_addr; 
    printf( "Official hostname: %s  address: %s\n", 
            hptr->h_name, inet_ntoa(addr) ); 
 
    /* 
     * lookup local host record by address 
     */ 
 
    hptr = gethostbyaddr( &addr.s_addr, sizeof(addr.s_addr), AF_INET );  (3)
    if ( !hptr ) 
        { 
        perror( "Failed to find record for local host" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    printf( "Back-translated hostname: %s\n", hptr->h_name ); 
 
    exit( EXIT_SUCCESS ); 
} 

In this example, the following functions and arguments were used to find a local host name and address:

  1. gethostname() gets the local host name.
    host is the address of the buffer that receives the host name.
    sizeof(host) is the size of the buffer that receives the host name.
  2. gethostbyname() looks for the host record that has the specified name.
    On successful return of the gethostbyname() function, hptr receives the address of a hostent structure containing the host name, alias names, host address type, length of address (4 or 16), and an array of IPv4 addresses of the host being sought.
  3. gethostbyaddr() looks for the host record that has the specified address.
    addr.s_addr specifies the address of the host being sought. It points to a series of bytes in network order, not to an ASCII string.
    sizeof(addr.s_addr) specifies the number of bytes in the address to which the first argument points.
    AF_INET points to the supported address family.

2.16.2 BIND Lookups (System Services)

If BIND is enabled on your system, the IO$_ACPCONTROL function searches the BIND database for the host name if it does not find the name in the local host database. The p1 argument allows you to specify the gethostbyaddr() or gethostbyname() network ACP subfunctions to control how the function searches the database.

Example 2-25 shows how to use OpenVMS system services to find a host name and address.

Example 2-25 BIND Lookup (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            */ 
 
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 acpfunc 
    {                                   /* acp subfunction                  */ 
    unsigned char code;                 /* subfunction code                 */ 
    unsigned char type;                 /* call code                        */ 
    unsigned short reserved;            /* reserved (must be zero)          */ 
    }; 
 
 
int main( void ) 
{ 
    char host[1024]; 
    char hostent[2048]; 
    struct in_addr addr; 
    struct hostent *hptr; 
 
    struct iosb iosb;                   /* i/o status block                 */ 
    unsigned int status;                /* system service return status     */ 
    unsigned short channel;             /* network device i/o channel       */ 
 
    struct acpfunc func_byaddr =        /* acp gethostbyaddr function code  */ 
        { INETACP_FUNC$C_GETHOSTBYADDR, INETACP$C_HOSTENT_OFFSET, 0 }; 
 
    struct acpfunc func_byname =        /* acp gethostbyname function code  */ 
        { INETACP_FUNC$C_GETHOSTBYNAME, INETACP$C_HOSTENT_OFFSET, 0 }; 
 
    struct dsc$descriptor p1_dsc =      /* acp function descriptor          */ 
        { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 }; 
 
    struct dsc$descriptor p2_dsc =      /* acp p2 argument descriptor       */ 
        { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 }; 
 
    struct dsc$descriptor p4_dsc =      /* acp p4 argument descriptor       */ 
        { 0, DSC$K_CLASS_S, DSC$K_DTYPE_T, 0 }; 
 
    $DESCRIPTOR( inet_device,           /* string descriptor with logical   */ 
                 "TCPIP$DEVICE:" );     /* name of network pseudodevice     */ 
 
    /* 
     * get name of local host 
     */ 
 
    if ( (gethostname(host, sizeof(host))) < 0 ) 
        { 
        perror( "Failed to get host's local name" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    printf( "Local hostname: %s\n", host ); 
    /* 
     * 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 ); 
        } 
 
    /* 
     * lookup local host record by name 
     */ 
 
    p1_dsc.dsc$w_length  = sizeof(func_byname); 
    p1_dsc.dsc$a_pointer = (char *) &func_byname; 
 
    p2_dsc.dsc$w_length  = strlen( host ); 
    p2_dsc.dsc$a_pointer = host; 
 
    p4_dsc.dsc$w_length  = sizeof(hostent); 
    p4_dsc.dsc$a_pointer = hostent; 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_ACPCONTROL,      /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       &p1_dsc,             /* p1 - acp subfunction code    */ 
                       &p2_dsc,             /* p2 - hostname to lookup      */ 
                       &p4_dsc.dsc$w_length,/* p3 - return length address   */ 
                       &p4_dsc,             /* p4 - output buffer address   */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to find record for local host\n" ); 
        exit( status ); 
        } 
    hptr = (struct hostent *) hostent; 
    hptr->h_name += (unsigned int) hptr; 
    *(char **) &hptr->h_addr_list += (unsigned int) hptr; 
    *(char **) hptr->h_addr_list  += (unsigned int) hptr; 
 
    addr.s_addr = *(int *) hptr->h_addr; 
    printf( "Official hostname: %s  address: %s\n", 
            hptr->h_name, inet_ntoa(addr) ); 
 
    /* 
     * lookup local host record by address 
     */ 
 
    p1_dsc.dsc$w_length  = sizeof(func_byaddr); 
    p1_dsc.dsc$a_pointer = (char *) &func_byaddr; 
 
    p2_dsc.dsc$w_length  = strlen( inet_ntoa(addr) ); 
    p2_dsc.dsc$a_pointer = inet_ntoa( addr ); 
 
    p4_dsc.dsc$w_length  = sizeof(hostent); 
    p4_dsc.dsc$a_pointer = hostent; 
 
    status = sys$qiow( EFN$C_ENF,           /* event flag                   */ 
                       channel,             /* i/o channel                  */ 
                       IO$_ACPCONTROL,      /* i/o function code            */ 
                       &iosb,               /* i/o status block             */ 
                       0,                   /* ast service routine          */ 
                       0,                   /* ast parameter                */ 
                       &p1_dsc,             /* p1 - acp subfunction code    */ 
                       &p2_dsc,             /* p2 - ip address to lookup    */ 
                       &p4_dsc.dsc$w_length,/* p3 - return length address   */ 
                       &p4_dsc,             /* p4 - output buffer address   */ 
                       0,                   /* p5                           */ 
                       0                    /* p6                           */ 
                     ); 
 
    if ( status & STS$M_SUCCESS ) 
        status = iosb.status; 
 
    if ( !(status & STS$M_SUCCESS) ) 
        { 
        printf( "Failed to find record for local host\n" ); 
        exit( status ); 
        } 
 
    hptr = (struct hostent *) hostent; 
    hptr->h_name += (unsigned int) hptr; 
 
    printf( "Back-translated hostname: %s\n", hptr->h_name ); 
 
    /* 
     * 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.17 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, and 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.17.1 Closing and Deleting (Sockets API)

Example 2-26 shows a TCP application using the close() function to close and delete a socket.

Example 2-26 Closing and Deleting 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 ); 
        } 
 
    /* 
     * close socket 
     */ 
 
    if ( close(sockfd) < 0 )  (1)
        { 
        perror( "Failed to close socket" ); 
        exit( EXIT_FAILURE ); 
        } 
 
    exit( EXIT_SUCCESS ); 
} 

(1) The sockfd argument for the close() function closes the socket and deletes the socket descriptor previously defined by the socket() function.


Previous Next Contents Index