HP OpenVMS SystemsC Programming Language
This appendix describes the aspects of the Compaq C language that pertain to the writing of Internet application programs for the TCP/IP Services for OpenVMS product (formerly the VMS/ULTRIX Connection). TCP/IP Services for OpenVMS is the Compaq implementation of the TCP/IP (Transmission Control Protocol/Internet Protocol) protocol.
For a description of Internet details, such as protocols, protocol types, and sockets, see the TCP/IP Services for OpenVMS System Management. For more information on how to write socket programs, see the UNIX Supplementary Documents, System Manager.
This section contains information that you should consider when writing Internet application programs for the TCP/IP Services for OpenVMS. These considerations will help to make your programs more portable.
Calls to various Interprocess Communication (IPC) routines use a static area within which they return information. The OpenVMS environment allows an asynchronous system trap (AST) routine to interrupt an IPC routine during its execution. In addition, the ASTs of more privileged modes can interrupt ASTs of less privileged modes. Therefore, caution needs to be observed when calling an IPC routine from an AST state, while a similar IPC routine is being called from a non-AST state or a less privileged mode.
The IPC routines that use a static area are:
Several IPC routines access files in order to retrieve their information. These routines should not be called from either the KERNEL or EXEC modes when ASTs are disabled. These IPC routines are:
Certain parameters to the IPC routines may require type casting to suppress Compaq C compilation warnings. Type casting is required because of parameter prototyping, which the Compaq C header ( .h ) files have in order to be ANSI compliant. These header files are unlike UNIX header files, whose IPC routines are not parameter prototyped.
It is acceptable to include header files on an OpenVMS system without using angle brackets (< >) or double quotes (" "). For example, #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 UNIX systems, however, header files must be specified with angle brackets (< >) or double quotes (" ") and any subdirectories that are needed to locate a header file. For example, to include the header file socket.h , use the following form of the #include directive:
The socket routines make use of several Compaq C structures. Table A-1 lists these structures and the header files in which they are defined.
|Structure Name||Header File|
The Internet protocol family is a collection of protocols layered on the Internet Protocol (IP) transport layer, and using the Internet address format. This section describes the Transmission Control Protocol and User Datagram Protocol.
The Transmission Control Protocol (TCP) provides a reliable, flow-controlled, two-way transmission of data. It is a byte-stream protocol used to support the SOCK_STREAM abstraction. TCP uses the standard Internet address format and, in addition, provides a per host collection of port addresses. Thus, each address is composed of an Internet address specifying the host and network with a specific TCP port on the host identifying the peer entity.
Sockets utilizing the TCP protocol are either active or passive. Active sockets initiate connections to passive sockets. By default, TCP sockets are created active; to create a passive socket the listen system call must be used after binding the socket with the bind system call. Only passive sockets may use the accept call to accept incoming connections. Only active sockets may use the connect call to initiate 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. To create a socket that listens to all hosts on any network, the Internet address INADDR_ANY must be bound. The TCP port must be specified at this time. If the Internet address is not INADDR and the port is not specified, the system will assign a port. Once a connection has been established, 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 are being transmitted and received. Normally this address corresponds to the peer entity's network.
TCP supports one socket option that is set with setsockopt and tested with getsockopt . Under most circumstances, TCP sends data when it is presented; when outstanding data has not yet been acknowledged, it gathers small amounts of output to be sent in a single packet once an acnowledgement 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 may 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, which is available from getprotobyname .
User Datagram Protocol (UDP) is a simple, unreliable datagram protocol used to support the SOCK_DGRAM abstraction for the Internet protocol family. UDP sockets are connectionless and are normally used with the sendto and recvfrom calls, though the connect call may also be used to fix the destination for future packets (in which case the recv or read or write system calls may be used).
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 may not be connected to a TCP port). Also, broadcast packets may be sent (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 the SYSPRV or BYPASS privilege for broadcasting to succeed.
errno is an external variable whose value is set whenever an error occurs during a call to any of the Compaq C RTL routines. You can use this value to obtain a more detailed description of the error. errno is not cleared on successful calls, so its value should be checked only when an error has been indicated.
Most calls to the Compaq C RTL routines have one or more returned values. Any error condition is indicated by an otherwise impossible return value. This is almost always --1; the individual routine descriptions specify the details.
All return codes and values from routines are of type int unless otherwise noted. An error number is also made available in the external variable errno , which is not cleared on successful calls. The errno values may be translated to a message, similar to that found in UNIX systems, by using the perror routine. vaxc$errno may also be returned as an error.
The notation [...] is used in this manual to denote an errno error.
Table A-2 lists the errno values.
|EINPROGRESS||Operation now in progress|
|An operation that takes a long time to complete, such as connect , was attempted on a nonblocking object.|
|EALREADY||Operation already in progress|
|An operation was attempted on a nonblocking object that already had an operation in progress.|
|ENOTSOCK||Socket operation on a non-socket|
|EDESTADDRREQ||Destination address required|
|A required address was omitted from an operation on a socket.|
|EMSGSIZE||Message too long|
|A message sent on a socket was larger than the internal message buffer.|
|EPROTOTYPE||Protocol wrong type for socket|
|A protocol was specified that does not support the semantics of the socket type requested. For example, you cannot use the ARPA Internet UDP protocol with type SOCK_STREAM.|
|ENOPROTOOPT||Protocol not available|
|A bad option was specified in a getsockopt or setsocketopt call.|
|EPROTONOSUPPORT||Protocol not supported|
|The protocol has not been configured into the system or no implementation for it exists.|
|ESOCKTNOSUPPORT||Socket type not supported|
|The support for the socket type has not been configured into the system or no implementation for it exists.|
|EOPNOTSUPP||Error-operation not supported|
|For example, trying to accept a connection on a datagram socket.|
|EPFNOSUPPORT||Protocol family not supported|
|The protocol family has not been configured into the system or no implementation for it exists.|
|EAFNOSUPPORT||Address family not supported by protocol family|
|An address incompatible with the requested protocol was used.|
|EADDRINUSE||Address already in use|
|Each address can be used only once.|
|EADDRNOTAVAIL||Cannot assign requested address|
|Normally, results from an attempt to create a socket with an address not on this machine.|
|ENETDOWN||Network is down|
|A socket operation encountered a dead network.|
|ENETUNREACH||Network is unreachable|
|A socket operation was attempted to an unreachable network.|
|ENETRESET||Network dropped connection on reset|
|The host you were connected to crashed and rebooted.|
|ECONNABORTED||Software caused connection abort|
|A connection abort was caused internal to your host machine.|
|ECONNRESET||Connection reset by peer|
|A connection was forcibly closed by a peer. This usually results from the peer executing a shutdown call.|
|ENOBUFS||No buffer space available|
|An operation on a socket or pipe was not performed because the system lacked sufficient buffer space.|
|EISCONN||Socket is already connected|
|A connect request was made on an already connected socket; or, a sendto or sendmsg request on a connected socket specified a destination other than the connected party.|
|ENTOTCONN||Socket is not connected|
|Request to send or receive data was disallowed because the socket is not connected.|
|ESHUTDOWN||Cannot send after socket shutdown|
|A request to send data was disallowed because the socket had already been shut down with a previous shutdown call.|
|ETOOMANYREFS||Too many references: cannot splice|
|ETIMEDOUT||Connection timed out|
|A connect request failed because the connected party did not properly respond after a period of time. (The timeout period is dependent on the communication protocol.) A connect request or remote file operation failed because the connected party did not properly respond after a period of time that is dependent on the communication protocol.|
|No connection could be made because the target machine actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host.|
|ELOOP||Too many levels of symbolic links|
|A path name lookup involved more than eight symbolic links.|
|ENAMETOOLONG||File name too long|
|A component of a path name exceeded 255 characters, or an entire path name exceeded 1023 characters.|
|EHOSTDOWN||Host is down|
|A socket operation failed because the destination host was down.|
|EHOSTUNREACH||No route to host|
|A socket operation was attempted to an unreachable host.|
|EVMSERR||OpenVMS system-specific error code that is nontranslatable|
The external integer h_errno is available only with OpenVMS Version 7.0, and is set only by a 4.4BSD TCP/IP interface. Specifically, The gethostbyname and gethostbyaddr functions require 4.4BSD semantics to set h_errno . The gethostbyname and gethostbyaddr functions indicate an error condition by returning a null pointer and setting the external integer h_errno to indicate the error return status.
When gethostbyname or gethostbyaddr returns an error status, h_errno , which is very similar to errno , can be checked to determine whether the error is the result of a temporary failure or an invalid or unknown host.
Use the herror routine to print the error message describing the failure. If the argument string to herror is not NULL, it is printed, followed by a colon (:) and a space. The error message is printed with a trailing new-line character.
The h_errno error codes are not available with the errno variable.
The <netdb.h> header file declares h_errno on a per-thread basis as:
#define h_errno (*decc$h_errno_get_addr())
The <netdb.h> header file also symbolically defines the error code values that h_errno can accept, as follows:
|HOST_NOT_FOUND||No such host is known.|
|TRY_AGAIN||Usually a temporary error that means the local server did not receive a response from an authoritative server. A retry at some later time can succeed.|
|NO_RECOVERY||An unexpected server failure is encountered. This is a nonrecoverable error.|
|NO_DATA||The requested name is valid but does not have an IP address; this is not a temporary error. The name is known to the name server but there is no address associated with this name. Another type of request to the name server using this domain name results in an answer; for example, a mail-forwarder registered for this domain.|
|NO_ADDRESS||No address; look for MX record|