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


Previous Contents Index


Chapter 5
Using DEC C Socket Routines

This chapter contains information to help you increase the portability of the internet application programs that you write for the DIGITAL TCP/IP Services for OpenVMS software.

For more information on writing socket programs, see the DEC C Run-Time Library Reference Manual for OpenVMS Systems.

5.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.

5.1.1 TCP Sockets

TCP provides reliable, flow-controlled, two-way transmission of data. TCP is 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. The following table lists the differences between these socket types.

Table 5-1 TCP Socket Type Descriptions
Socket Type Description
Active sockets Initiate connections to passive sockets. By default, TCP sockets are created active.
  Only active sockets can use the connect() call to initiate connections.
Passive sockets To create a passive socket, use the listen() system call after binding the socket with the bind() system call.
  Only passive sockets can use the accept() call to accept incoming connections.
  Passive sockets may underspecify their location to match incoming connection requests from multiple networks. This technique, called wildcard addressing, allows a single server to provide service to clients on multiple networks.

5.1.1.1 Wildcard Addressing

Create a socket that listens to all hosts on any network, as follows:

  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 1024. 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 one socket option set with the setsockopt() and tested with getsockopt. 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 <netinet/tcp.h>), to defeat this algorithm. The option level for the setsockopt() call is the protocol number for TCP, available from getprotobyname().

5.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() calls. You can also use the connect() call to fix the destination for future packets (in which case, you can use the recv() or read() or write() system calls).

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 SYSPRV, BYPASS, or OPER privileges for broadcasting to succeed.

5.2 Calling a C Socket Routine from an AST State

Calls to various C Socket routines return information within a static area. The OpenVMS environment allows an asynchronous system trap (AST) routine to interrupt a C Socket routine during its execution. In addition, the ASTs of more privileged modes can interrupt ASTs of less privileged modes. Therefore, observe caution when calling a C Socket routine from an AST state while a similar C Socket routine is being called from a non-AST state or a less privileged access mode.

The C Socket routines that use a static area are:

5.3 Calling From KERNEL or EXEC Modes

Several C Socket routines access files in order to retrieve their information. You should not call these routines from either the KERNEL or EXEC modes when the ASTs are disabled. These C Socket routines are:

5.4 Standard I/O

You cannot use standard I/O with sockets. The fdopen function does not support sockets.

5.5 Event Flags

C Socket routines can use event flags during their operation. To assign event flags, use the library routine LIB$GET_EF. The flags are released when the routine no longer needs them.

5.6 Suppressing DEC C Compilation Warnings

Certain parameters to the DIGITAL TCP/IP Services for OpenVMS C Socket routines require typecasting to suppress DEC C compilation warnings. Typecasting is required because of parameter prototyping, which the DEC C header (.h) files have in order to comply with ANSI standards. The DIGITAL UNIX header files have different requirements because their C Socket routines are not parameter prototyped.

5.7 Header Files

You can include header files on a OpenVMS system without using angle brackets:


#include types 

This form of the #include preprocessor directive is possible on OpenVMS systems because all header files are located in a text library in SYS$LIBRARY. On DIGITAL UNIX systems, you must specify header files with angle brackets (< >) or double quotes (" ") and subdirectories that locate a header file.

For example, to include the header file types.h, you would use the following form of the #include directive:


#include <sys/types.h> 

5.8 DEC C Structures

This section describes the structures you can use when writing internet applications for OpenVMS software.

5.8.1 hostent Structure

The hostent structure, defined in the <netdb.h> header file, specifies or obtains a host name, a list of aliases associated with the network, and the network's number as specified in an internet address from the hosts database. An entry in the hosts database is created with the following command:


TCPIP> SET HOST xxxx 

The DIGITAL TCP/IP Services for OpenVMS Management guide contains a description of the hosts database.

The hostent structure is defined as follows:


struct  hostent { 
        char    *h_name;(1)        /* official name of host */ 
        char    **h_aliases;(2)    /* alias list */ 
        int     h_addrtype;(3)     /* host address type */ 
        int     h_length;(4)       /* length of address */ 
        char    **h_addr_list;(5)  /* list of addresses from name server */ 
#define h_addr  h_addr_list[0](6)  /* address, for backward compatibility */ 
}; 

The members of the hostent structure are:

  1. h_name is a pointer to a null-terminated character string that is the official name of the host.
  2. h_aliases is a null-terminated array of alternate names for the host.
  3. h_addrtype is the type of address being returned. Currently, this is AF_INET.
  4. h_length is the length, in bytes, of the address.
  5. h_addr_list is a pointer to a list of pointers to the network addresses for the host. Each host address is represented by a series of bytes in network order. They are not ASCII strings.
  6. h_addr is defined as the first address in the h_addr_list. This is used for backward compatibility.

5.8.2 in_addr Structure

The in_addr structure, defined in the <in.h> header file, specifies or obtains an internet address. The address format can be any of the supported internet address notation formats. For information about internet address notation, see the DIGITAL TCP/IP Services for OpenVMS Management.

The in_addr structure is defined as follows:


struct in_addr { 
       union { 
                struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; 
                struct { u_short s_w1,s_w2; } S_un_w; 
                u_long S_addr; 
}      S_un; 
#define s_addr  S_un.S_addr     /* can be used for most tcp & ip code */ 
#define s_host  S_un.S_un_b.s_b2        /* host on imp */ 
#define s_net   S_un.S_un_b.s_b1        /* network */ 
#define s_imp   S_un.S_un_w.s_w2        /* imp */ 
#define s_impno S_un.S_un_b.s_b4        /* imp # */ 
#define s_lh    S_un.S_un_b.s_b3        /* logical host */ 
}; 

5.8.3 iovec Structure

On DECnet-Plus for DIGITAL UNIX systems, the iovec structure is defined in the <uio.h> header file. On OpenVMS systems, it is defined in the <socket.h> header file.

The iovec structure describes one scatter/gather buffer. Multiple scatter/gather buffer descriptors are stored as an array of iovec elements.

The iovec structure is defined as follows:


struct iovec { 
       char *iov_base;(1)
       int  iov_len;(2)
} 

The members of the iovec structure are:

  1. iov_base is a pointer to a buffer.
  2. iov_len contains the size of the buffer to which iov_base points.

5.8.4 linger Structure

The linger structure, defined in the <socket.h> header file, specifies the setting or resetting of the socket option for the time interval that the socket lingers for data. The linger structure is supported only by STREAM type sockets.

The linger structure is defined as follows:


struct  linger { 
        int     l_onoff;(1)       /* option on/off */ 
        int     l_linger;(2)      /* linger time */ 
}; 

The members of the linger structure are:

  1. l_onoff=1 sets the linger or l_onoff=0 resets the linger.
  2. l_linger is the number of seconds to linger (the default is 120, or 2 minutes).

5.8.5 msghdr Structure

The msghdr structure specifies the buffer parameter for the recvmsg and sendmsg I/O functions. The structure allows you to specify an array of scatter/gather buffers. The recvmsg function scatters the data to several user receive buffers, and the sendmsg function gathers data from several user transmit buffers before being transmitted.

The <socket.h> header file defines the following structures for BSD Versions 4.3 and 4.4:

5.8.5.1 Structure for BSD Version 4.4

The msghdr structure for use with BSD Version 4.4 is defined as follows:


struct msghdr { 
       void         *msg_name;(1)       /* protocol address */ 
       int          msg_namelen;(2)     /* size of address */ 
       struct iovec *msg_iov;(3)        /* scatter/gather array */ 
       int          msg_iovlen;(4)      /* number of elements in msg_iov */ 
       void         *msg_control;(5)    /* ancillary data; must be aligned 
                                               for a cmsghdr structure */ 
       int          msg_controllen;(6)  /* length of ancillary data buffer */ 
       int          msg_flags;(7)       /* flags on received message */ 
}; 
 

The members of the msghdr structure are:

  1. msg_name is the address of the destination socket if the socket is not connected. If no address is required, you can set this field to null.
  2. msg_namelen is the length of the msg_name field.
  3. msg_iov is an array of I/O buffer pointers of the iovec structure form. See Section 5.8.3 for a description of the iovec structure.
  4. msg_iovlen is the number of buffers in the msg_iov array.
  5. msg_control specifies the location of the optional ancillary data, or control information.
  6. msg_controllen is the size of the ancillary data in the msg_control buffer.
  7. mgs_flags, used only with the recvmsg function, is the value used by the kernel to drive its receive processing.

5.8.5.2 Structure for BSD Version 4.3

The omsghdr structure for use with BSD Version 4.3 is defined as follows:


struct omsghdr { 
       char          *msg_name;(1)       /* protocol address */ 
       int           msg_namelen;(2)     /* size of address */ 
       struct iovec  *msg_iov;(3)        /* scatter/gather array */ 
       int           msg_iovlen;(4)      /* number of elements in msg_iov */ 
       char          *msg_accrights;(5)  /* access rights sent/received */ 
       int           msg_accrightslen;(6)/* length of access rights buffer */ 
}; 

The members of the omsghdr structure are:

  1. msg_name is the address of the destination socket if the socket is not connected. If no address is required, you can set this field to null.
  2. msg_namelen is the length of the msg_name field.
  3. msg_iov is an array of I/O buffer pointers of the iovec structure form. See Section 5.8.3 for a description of the iovec structure.
  4. msg_iovlen is the number of buffers in the msg_iov array.
  5. msg_accrights points to a buffer containing access rights sent with the message.
  6. msg_accrightslen is the length of the msg_accrights buffer.

5.8.6 netent Structure

The netent structure, defined in the <netdb.h> header file, specifies or obtains a network name, a list of aliases associated with the network, and the network's number specified as an internet address from the network database. An entry in the network database is created with the following command:


TCPIP> SET NETWORK xxxx 

The DIGITAL TCP/IP Services for OpenVMS Management guide contains a description of the network database.

The netent structure is defined as follows:


struct  netent { 
        char    *n_name;(1)       /* official name of net */ 
        char    **n_aliases;(2)   /* alias list */ 
        int     n_addrtype;(3)    /* net address type */ 
        long    n_net;(4)         /* net number */ 
}; 

The members of the netent structure are:

  1. n_name is the official network name.
  2. n_aliases is a null-terminated list of pointers to alternate names for the network.
  3. n_addrtype is the type of the network number returned. Currently this type is always AF_INET.
  4. n_net is the network number, returned in host byte order.

5.8.7 sockaddr Structure

The sockaddr structure, defined in the <socket.h> header file, specifies a general address family.

The <socket.h> header file defines the following structures for BSD Versions 4.3 and 4.4:

5.8.7.1 Structure for BSD Version 4.4

The sockaddr structure for use with BSD Version 4.4 is defined as follows:


   struct sockaddr { 
           u_char  sa_len;(1)      /* total length */ 
           u_char  sa_family;(2)   /* address family */ 
           char    sa_data[14];(3) /* up to 14 bytes of direct address */ 
}; 
 

The members of the sockaddr structure are:

  1. sa_len is the length of the structure.
  2. sa_family is the address family or domain in which the socket was created.
  3. sa_data is the data string of up to 14 bytes of direct address.

5.8.7.2 Structure for BSD Version 4.3

The osockaddr structure for use with BSD Version 4.3 is defined as follows:


   struct osockaddr { 
          u_short sa_family;(1)     /* address family */ 
          char    sa_data[14];(2)   /* up to 14 bytes of direct address */ 
}; 
 

The members of the osockaddr structure are:

  1. sa_family is the address family or domain in which the socket was created.
  2. sa_data is the data string of up to 14 bytes of direct address.

5.8.8 sockaddr_in Structure

The sockaddr_in structure, defined in the <in.h> header file, specifies an internet address family.

The sockaddr_in structure is defined as follows:


 
struct sockaddr_in { 
        short   sin_family;(1)       /* address family */ 
        u_short sin_port;(2)         /* port number */ 
        struct  in_addr sin_addr;(3) /* internet address */ 
        char    sin_zero[8];(4)      /* 8-byte field of all zeroes */ 
}; 
 

The members of the sockaddr_in structure are:

  1. sin_family is the address family (internet domain (AF_INET)).
  2. sin_port is the port number in network order.
  3. sin_addr is the internet address in network order.
  4. sin_zero is an 8-byte field containing all zeros.

5.8.9 timeval Structure

The timeval structure, defined in the <socket.h> header file, specifies time intervals. This structure is defined as follows:


struct timeval { 
    long tv_sec;(1)
    long tv_usec;(2)
}; 

The members of the timeval structure are:


Previous Next Contents Index