The BSD UNIX Socket Library

Introduction

This chapter contains a discussion of the Berkeley Software Distribution (BSD) UNIX Socket Library and the application programming interface for writing TCP/IP applications using the SAS/C Compiler. It also describes the purpose of each header file. Finally, it describes the basic mechanics of communicating through sockets, along with a summary of the socket functions provided with the SAS/C Compiler.

Overview of the BSD UNIX Socket Library

BSD UNIX communications programming is based on the original UNIX framework, with some additions and elaborations to take into account the greater complexity of interprocess communications. In traditional UNIX file I/O, an application issues an open call, which returns a file descriptor (a small integer) bound to a particular file or device. The application then issues a read or write call that causes the transfer of stream data. At the end of communications, the application issues a close call to terminate the interaction.

Because interprocess communication often takes place over a network, the BSD UNIX Socket Library takes into account the numerous variables of network I/O, such as network protocols, in addition to the semantics of the UNIX file system.

Briefly stated, a socket is an end point for interprocess communication, in this case, over a network running TCP/IP. The socket interface can support a number of underlying transport mechanisms. Ideally, a program written with socket calls can be used with different network architectures and different local interprocess communication facilities with few or no changes. The SAS/C Compiler supports TCP/IP and the AF_INET Internet addressing family.

Sockets can simultaneously transmit and receive data from another process, using semantics that depend on the type of socket. There are three types of sockets: stream, datagram, and raw, each of which represents a different type of communications service.

Stream sockets provide reliable, connection-based communications. In connection-based communications, the two processes must establish a logical connection with each other. A stream of bytes is then sent without errors or duplication and is received in the order in which it was sent. Stream sockets correspond to the TCP protocol in TCP/IP.

Datagram sockets communicate via discrete messages, called datagrams, which are sent as packets. Datagram sockets are connectionless; that is, the communicating processes do not have a logical connection with each other. The delivery of their data is unreliable. The datagrams can be lost or duplicated, or they may not arrive in the order in which they were sent. Datagram sockets correspond to the UDP protocol in TCP/IP.

Raw sockets provide direct access to the lower-layer protocols, for example, IP and the Internet Control Message Protocol (ICMP).

If you are communicating with an existing application, you must use the same protocols as that application. When symbols defined in the header files are passed as parameters to the socket functions, you can change options and variables, such as whether your communications are connection-oriented or connectionless and what network names you want to send to or receive from.

In network operations, an application can specify a different destination each time it uses a socket. It is also possible to send datagrams of varying length, in addition to stream data. The socket interface enables you to create both servers that await connections and clients that initiate the connections using services in addition to open, read, write, and close.

Another factor that makes communicating over a network more complex than traditional UNIX I/O is the problem of ascertaining the correct addresses for clients and servers, and of converting information from one format to another as it travels between different machines on different networks in the Internet. The socket library provides Internet addressing utility functions and network information functions to resolve these issues.

Header Files

The SAS/C Socket Library provides header files to enable you to program with socket functions. A list of the header files, accompanied by a brief description of each one and an explanation of its structures, follows. Refer to Header Filenames for a discussion of header file naming conventions.

The header files in this section are listed in the following order:

  1. <sys/types.h>
  2. <sys/uio.h>
  3. <errno.h>
  4. <sys/ioctl.h>
  5. <fcntl.h>
  6. <sys/socket.h>
  7. <netdb.h>
  8. <netinet/in_systm.h>
  9. <netinet/ip_icmp.h>
  10. <netinet/udp.h>
  11. <netinet/ip.h>
  12. <netinet/in.h>
  13. <arpa/inet.h>
  14. <arpa/nameser.h>
  15. <resolv.h>
  16. <net/if.h>
  17. <strings.h>
In many cases the contents of one header file depend on the prior inclusion of another header file. The description for each header file lists any other header files on which the header file may depend. Failure to adhere to these ordering dependencies usually results in compilation errors. The order that the header files follow in this chapter reflects the dependencies between header files.

Note: Sockets are not defined by the POSIX.1 and POSIX.1a standards. Therefore, if your program uses sockets, you should not define the symbol _POSIX_SOURCE, as this will exclude socket-related types from standard POSIX header files such as <sys/types.h>.

<sys/types.h>

This header file contains definitions to allow for the porting of BSD programs.

<sys/types.h> must usually be included before other socket-related header files; refer to the individual header file descriptions that follow for the specific dependency.

This header file declares the following typedef names for use as abbreviations for three commonly used types:

The following typedef name is commonly used for buffer pointers:
 typedef char * caddr_t;
 
This header file also defines the FD_SET, FD_ZERO, FD_CLR, FD_ISSET, and FD_SETSIZE macros used by select to manipulate socket descriptors. Refer to Socket Function Reference for a description of these macros.

timeval

This structure is used by the select call to set the amount of time for a user process to wait.
 struct timeval {
    long tv_sec;     /* seconds      */ 
    long tv_usec;    /* microseconds */ 
 };
 
For more information on the inclusion of this structure in the <sys/types.h> header file, refer to Porting UNIX Socket Applications to the SAS/C® Environment

<sys/uio.h>

The structure in the <sys/uio.h> header file is described in the following section. <sys/types.h> must be included before this header file.

iovec

This structure is used by the readv, writev, sendmsg, and recvmsg calls. An array of iovec structures describes the pieces of a noncontiguous buffer.
 struct iovec {
    void * iov_base;
    int    iov_len;
 };
 

<errno.h>

This header file contains definitions for the macro identifiers that name system error status conditions. When a SAS/C Library function sets an error status by assigning a nonzero value to errno, the calling program can check for a particular value by using the name defined in <errno.h>. The following table lists all the errno values normally associated with the socket library functions:
  Errno Value     perror message         Explanation

   EACCES          permission denied      The program does not have access to
                                          this socket.

   EADDRINUSE      socket address is      The given address is already in use.

   EADDRNOTAVAIL   socket address not     The given address is not available on
                   usable                 the local host.

   EAFNOSUPPORT    unsupported socket     The addressing family is not
                   addressing family      supported or is not consistent with
                                          socket type.  The SAS/C Library
                                          supports only AF_INET (and AF_UNIX if
                                          integrated sockets are used).

   EALREADY        previous connection    The socket is marked for non-blocking
                   not yet completed      I/O, and an earlier connect call has not
                                          yet completed.

   EBADF           file or socket not     The descriptor value passed does not
                   open or unsuitable     correspond to an open socket or file.

   ECONNABORTED    connection aborted     The local communications software
                   by local network       aborted the connection.
                   software              

   ECONNREFUSED    destination host       The destination host refused the
                   refused socket         socket connection.
                   connection            

   ECONNRESET      connection reset by    The peer process has reset the
                   peer                   connection.

   EDESTADDRREQ    socket operation       Supply a destination address 
                   requires               for this socket.
                   destination address   

   EHOSTDOWN       destination host is    The destination host is down.
                   down                 

   EHOSTUNREACH    destination host is    The destination host is unreachable.
                   unreachable           

   EINPROGRESS     socket connection      The connection has begun, but
                   in progress            control is returned so that
                                          the call will not block.  The
                                          connection is complete when the
                                          select call indicates that the
                                          socket is ready for writing.  This is
                                          not an error.

   EISCONN         socket is already      The program called connect on a
                   connected              connected socket.

   EMSGSIZE        message too large      A datagram socket could not
                   for datagram socket    accommodate a message as large as
                                          this one.

   ENETDOWN        local host's           The program cannot talk to the
                   network down or        networking software on this
                   inaccessible           local machine, or the host's
                                          network is down.

   ENETRESET       remote host dropped    The remote host is not communicating
                   network                over the network at this time.
                   communications
        
   ENETUNREACH     destination            This host cannot find a route
                   network is             to the destination network.
                   unreachable         
                                         

   ENOBUFS         insufficient           The operating system did not have
                   buffers in network     enough memory to perform the
                   software               requested operation

   ENOPROTOOPT     option not             The socket option or option level is
                   supported for          invalid.
                   protocol type       

   ENOTCONN        socket is not          The socket is not connected.
                   connected           

   ENOTSOCK        file descriptor        The given file descriptor is
                   not associated         either assigned to a file or is
                   with a socket          completely unassigned.

   EOPNOTSUPP      operation not          The call does not support this type
                   supported on           of socket.
                   socket              

   EPFNOSUPPORT    unsupported socket     The given protocol family is unknown
                   protocol family        or unsupported by the TCP/IP network
                                          software.

   EPIPE           broken pipe or         The peer process closed the socket
                   socket connection      before your process was finished with
                                          it.

   EPROTONOSUPPORT unsupported socket     The given protocol is unknown or not
                   protocol               supported by the TCP/IP network
                                          software.

   EPROTOTYPE      protocol               When calling the socket, the
                   inconsistent with      protocol was not 0 and not
                   socket type            consistent with the socket type.

   ESHUTDOWN       connection has         The connection has been shut down.
                   been shut down       

   ESOCKTNOSUPPORT socket type not        The program specified a socket
                   allowed                type that is not supported by the
                                          TCP/IP network software.

   ESYS            operating system       The underlying operating system
                   interface failure      software or the TCP/IP software
                                          returned an abnormal failure
                                          condition. Contact TCP/IP vendor.

   ETIMEDOUT       socket connection      The destination host did not
                   attempt timed out      respond to a connection request.

   EWOULDBLOCK     socket operation       The socket is marked for
                   would block            non-blocking I/O, and the call
                                          would have been blocked. This is
                                          not an error. 
 

Note: Socket library functions may occasionally set errno values not shown in the above table. In particular, when integrated sockets are used, OpenEdition defined errno values may be stored to indicate conditions specific to the OpenEdition implementation. Common SAS/C errno values are listed in Chapter 1, "Introduction to the SAS/C Library," in SAS/C Library Reference, Volume 1 . Also refer to POSIX and OpenEdition Error Numbers for OpenEdition related errno values. For a complete listing of all errno values, see the SAS/C Compiler and Library Quick Reference Guide .

<sys/ioctl.h>

This header file contains definitions for the symbols required by the ioctl function, as well as the declaration for ioctl.

<fcntl.h>

This header file contains definitions for the constants associated with the fcntl function, as well as declarations for UNIX style I/O functions. Failure to include the <sys/uio.h> header file before this header file may result in a warning message if readv or writev is called.

<sys/socket.h>

This header file contains macro definitions related to the creation of sockets, for example, the type of socket (stream, datagram, or raw), the options supported, and the address family. (AF_UNIX is supported if integrated sockets are used.) The SAS/C Compiler only supports the TCP/IP and the AF_INET Internet address family. The <sys/socket.h> header file contains declarations for most of the functions that operate on sockets. You must include the <sys/types.h> header file before this header file. The structures in the <sys/socket.h> header file are described in the following sections.

linger

This structure is used for manipulating the amount of time that a socket waits for the transmission of unsent messages after the initiation of the close call.
 struct linger {
    int     l_onoff;          /* option on/off                      */ 
    int     l_linger;         /* linger time, in seconds            */ 
 };
 

sockaddr

This is a generic socket address structure. Because different underlying transport mechanisms address peer processes in different ways, the socket address format may vary.
 struct sockaddr {
    u_short sa_family;        /* address family                     */ 
    char    sa_data[14] ;     /* up to 14 bytes of direct address   */ 
 };
 

msghdr

This structure contains the message header for the recvmsg and sendmsg calls.
 struct msghdr {
    caddr_t msg_name;               /* optional address             */ 
    int     msg_namelen;            /* size of address              */ 
    struct  iovec *msg_iov;         /* scatter/gather array         */ 
 
    int     msg_iovlen;             /* # elements in msg_iov        */ 
    caddr_t msg_accrights;          /* ignored for AF_INET          */ 
    int     msg_accrightslen;       /* ignored for AF_INET          */ 
 };
 

clientid

This structure is used by the getclientid, givesocket, and takesocket routines. These routines allow MVS or CMS programs to pass socket descriptors. The routines compensate for the unavailablity of fork (except via OpenEdition) as a means of creating an independent process that shares file descriptors with its parent.
 struct clientid {
    int domain;          /* Such as AF_INET.                        */ 
    char name[8];        /* Address space or virtual machine name.  */ 
    char subtaskname[8]; /* Can be set to blank or a subask ID.     */ 
    char reserved20[20]; /* Do not use the contents of this         */ 
                         /* structure.                              */ 
 };

 

<netdb.h>

This header file contains structures returned by the network database library. Internet addresses and port numbers are stored in network byte order, identical to IBM 370 byte order. Other quantities, including network numbers, are stored in host byte order. Despite the fact that network byte order and host byte order are identical on the IBM System/370, a portable program must distinguish between the two. The structures in the <netdb.h> header file are described in the following sections.

hostent

This structure contains host information.
 struct hostent {
    char    *h_name;        /* official name of host                */ 
    char    **h_aliases;    /* alias list                           */ 
    int     h_addrtype;     /* host address type                    */ 
    int     h_length;       /* length of address                    */ 
    char    **h_addr_list;  /* list of addresses from name server   */ 
  #define h_addr h_addr_list[0]  /* address, for backward           */ 
                                 /* compatiblity                    */ 
 };
 

netent

This structure contains network information.
 struct  netent {
    char            *n_name;        /* official name of network     */ 
    char            **n_aliases;    /* alias list                   */ 
    int             n_addrtype;     /* net address type             */ 
                                    /* Only AF_INET is supported.   */ 
    unsigned long   n_net;          /* network number               */ 
 };
 

servent

This structure contains service information.
 struct  servent {
    char    *s_name;        /* official service name                */ 
    char    **s_aliases;    /* alias list                           */ 
    int     s_port;         /* port #                               */ 
    char    *s_proto;       /* protocol to use                      */ 
 };
 

protoent

This structure contains protocol information.
 struct  protoent {
    char    *p_name;        /* official protocol name               */ 
    char    **p_aliases;    /* alias list                           */ 
    int     p_proto;        /* protocol #                           */ 
 };
 

rpcent

<netdb.h> also defines a structure used to store information about programs using the Sun RPC protocol. This structure is defined as follows:
 struct rpcent {
    char    *r_name;        /* name of server for RPC program       */ 
    char    **r_aliases;    /* alias list                           */ 
    int     r_number;       /* RPC program number                   */ 
 };
 
Sun RPC programs can be identified by name or by number. The getrpcbyname function returns rpcent structure.

herror

The <netdb.h> header file also contains macro definitions for the integer h_errno, which describes name server conditions. Refer to Socket Function Reference for more information on h_errno.

<netinet/in.h>

This header file contains constants and structures defined by the Internet system. Several macros are defined for manipulating Internet addresses. Among these are INADDR_ANY, which indicates that no specific local address is required, and INADDR_NONE, which generally indicates an error in address manipulation functions. Refer to bind for more information on binding a local address to the socket.

You must include the <sys/types.h> header file before this header file. The structures in the <netinet/in.h> header file are described in the following sections.

in_addr

This structure contains the Internet address in network byte order, which is the same as host byte order on the IBM System/370.
 struct in_addr {
    u_long s_addr;
 };
 

sockaddr_in

This structure contains the socket address, which includes the host's Internet address and a port number. This is the specific address structure used for a socket address when the transport mechanism is TCP/IP.
 struct sockaddr_in {
    short   sin_family;
    u_short sin_port;
    struct  in_addr sin_addr;
    char    sin_zero[8];
 };
 

<netinet/in_systm.h>

This header file contains definitions to facilitate the porting of low-level network control and query Internetwork Control and Message Protocol (ICMP), and Internetwork Protocol (IP) raw socket type applications. The Internet ping client utility is an example of such a program.

<netinet/in_systm.h> must usually be included before other ICMP or IP socket related header files such as <netinet/ip.h> and <netinet/ip_icmp.h>. Refer to the individual header file descriptions that follow for the specific dependency.

This header declares the following typedef names for use as abbreviations for three commonly used types for internetwork order, that is types with the bytes in high endian order.

typedef u_short n_short;
declares unsigned short integer as received from the network.
typedef u_long n_long;
declares an unsigned long integer as received from the network.
typedef u_long n_time;
declares an unsigned long integer representing minutes and seconds since 00:00 Greenwich mean time, in byte reverse order.
The following definition is also available to kernel functions that provide a network time definition for the iptime function.
 #ifdef _KERNEL
 n_time iptime();
 #endif
 

<netinet/ip_icmp.h>

This header file contains definitions of constants and structures required for using the ICMP protocol as described in IBM's RFC 792. Prior inclusion of <netinet/in_systm.h> is required.

<netinet/ip.h>

This header file contains definitions of constants and structures required for using the IP protocol (Internet Protocol, Version 4) as described in IBM's RFC 791. Prior inclusion of <netinet/in_systm.h> is required.

<netinet/udp.h>

This header file contains definitions of the User Datagram Protocol (UDP) header for UDP datagrams. UDP datagrams consist of a fixed header section immediately followed by the data section. The length of entire datagram, including the header and data, is maintained in UDP length field as a count of the number of octets (an octet is 8

bits; on IBM S370/390 systems this is 1 byte) in the datagram. Thus, the mininum value is 8 (64 bits), which is the length of the header alone.

 struct udphdr {
     u_short uh_sport;  /* source port      */ 
     u_short uh_dport;  /* destination port */ 
     short uh_ulen;     /* udp length       */ 
     u_short uh_sum;    /* udp checksum     */ 
 };
 

<arpa/inet.h>

This header file contains declarations for the network address resolution functions. You must include the <netinet/in.h> header file before this header file.

<arpa/nameser.h>

This header file contains definitions that enable applications to communicate with Internet name servers. The contents of this header file are not of interest to most applications; however, this header file must be included before the <resolv.h> header file. Applications that manipulate resolver options must include this header file. You must include the <sys/types.h> header file before this header file.

<resolv.h>

This header file contains global definitions for the resolver. Definitions and structures in the <resolv.h> header file are discussed in the following sections. You must include the <sys/types.h>, <netinet/in.h>, and <arpa/nameser.h> header files before this header file.

state

_res refers to a state structure describing resolver operations. In the SAS/C implementation, _res is a macro. Because _res is not a variable, a program should not directly declare it. Inclusion of the <resolv.h> header file declares _res.
 struct state {
    int     retrans;                /* retransmition time interval     */ 
    int     retry;                  /* number of times to              */ 
                                    /* retransmit                      */ 
    long    options;                /* option flags - See below.       */ 
    int     nscount;                /* number of name servers          */ 
    struct  sockaddr_in nsaddr_list[MAXNS];  /* address of name        */ 
                                             /* server                 */ 
  #define nsaddr  nsaddr_list[0]    /* for backward compatibility      */ 
    u_short id;                     /* current packet id               */ 
    char    defdname[MAXDNAME];     /* default domain                  */ 
    char    *dnsrch[MAXDNSRCH+1];   /* components of domain to search  */ 
 };
 

Bitwise OR Options

The following bit masks are resolver options that can be specified. They are stored in _res.options.
RES_DEBUG
print resolver debugging messages.
RES_USEVC
use TCP connections rather than UDP datagrams for queries.
RES_STAYOPEN
when specified along with RES_USEVC, keep the TCP connection open between queries.
RES_RECURSE
for queries, set the recursion-desired bit. This is the default. res_send does not make queries iteratively. The name server handles recursion.
RES_DEFNAMES
have res_mkquery append the default domain name to single-component names. This is the default.
RES_DNSRCH
have gethostbyname search for host names in the current parent domains.
RES_IGNTC
ignore truncation errors; do not retry.

<net/if.h>

This header file contains structures that define the network interface and provide a packet transport mechanism. <net/if.h> is useful only for low-level programming of the network interface. You must include the <sys/types.h> and <sys/socket.h> header files before this header file.

<strings.h>

This header file provides compatibility with the BSD UNIX <strings.h> header file and the index, rindex, bzero, ffs, and bcmp functions. Refer to BSD Library Dependencies for more information on using these functions.

Socket Functions

The following scenario depicts a typical sequence of events in a network application using stream sockets:
  1. A server application issues a socket call, which returns an integer that is the socket descriptor, allocated to the AF_INET addressing family.
  2. The server uses the bind function to bind a name to the socket and allow the network access to the socket.
  3. The server issues the listen call to signal the network that it is ready to accept connections from other applications.
  4. The server issues an accept call to accept the connection request.
  5. A client application issues a connect call to the server.
  6. The client and server conduct read/write operations.
  7. The socket is disconnected with a close call.
Datagram sockets do not have to be bound or connected, but they normally need to acquire additional address information in order to communicate with each other.

The following sections describe the socket functions that gather information, convert data, and accompany each step in the process of communicating between applications over a network. Refer to Socket Function Reference for a complete description of each socket function.

Addresses and Network Information

The complexity of network communications frequently requires that an application have some means of determining the location of sockets or other applications and of acquiring information about the network.

Socket Address

A process may need to discover the address to which the socket is connected. The process may also need to discover its socket's local address. The following function calls determine socket addresses:

Host Name

The following function calls return the host's assigned name and the host's Internet address:

Address Manipulation

The following socket functions perform a translation between 32-bit IP addresses and the standard network dotted decimal notation, or they divide or reassemble the network and host sections of 32-bit IP addresses:

Host Information

An application can obtain information about a host by submitting either the host's name or its address. The following functions return the host name and IP address:

Network Information

An application can also obtain information about a network. The following function calls return network names and addresses:

Protocol Information

An application can also obtain information about protocols. The following function calls return protocol names and numbers:

Network Services

An application can obtain information about network services and their protocol ports. The following functions return network service names and ports:

Database Services

There are three sets of library routines that access a database to return information such as the names of machines and network services, and protocol port numbers. Generally speaking, these routines are of use only to applications, such as network management programs, that are intended to read the entire database.

With each set, an application can connect to a database, return a database entry, and disconnect. The pattern for the names of these routines is as follows:

X is the name of the database.

The following function calls perform database services:

Resolver Routines

These routines make, send, and interpret data packets for use with the Internet Domain Name Service. The resolver consists of the following socket functions: The following macros and functions place long and short integers in a buffer in the format expected by the Internet name server:

Data Conversion

Address or network information may need to be translated, and character sets received through a socket may need to be converted.

Byte Order Conversion

When an integer is copied from a network packet (unit of data) to a local machine or from a local machine to a network packet, the byte order must be converted between local machine byte order and network standard byte order. The following socket functions take a value as an argument and return that value with the bytes rearranged:

ASCII-EBCDIC Translation

The following functions translate between the ASCII character set generally used for text on the Internet, and the MVS or CMS EBCDIC character set:

Choosing a Socket Implementation

The SAS/C Socket Library supports both integrated and non-integrated sockets. Integrated sockets are available with OpenEdition and provide a higher degree of UNIX compatiblity. Non-integrated sockets rely on a run-time library implemented interface to TCP/IP software. The socket implementation is specified by the following function:

Creating a Socket

In order to create a socket, the application issues a socket call, specifying the domain and family to which the socket belongs. The program that creates the socket can also control factors such as length of timeout, type of data transmitted, and size of the communication buffer. Finally, the program can set operating characteristics of the socket such as whether an application can continue processing without becoming blocked during a recv call.

The following socket functions create a socket or control its operating characteristics:

Binding a Socket

A socket is created without associating it to any address. A local address can be bound to the socket with the following socket function:

Listening for a Connection

When an application in the role of server has opened a stream socket, it binds the socket to a local address and then waits for a connection request from another application. To avoid confusion in message delivery, the application can set up a queue for the incoming connection requests. The following socket function prepares the server to await incoming connections:

Connecting and Passing a Socket

Connecting a socket binds it to a permanent destination. If an application seeks to transmit data to a stream socket, it must first establish a connection to that socket. A server program can also pass sockets between two client programs. The following socket functions establish or pass connections between applications:

Accepting a Connection

After a server has established a socket, it waits for a connection. The following socket function causes the application to wait for a connect request:

Sending and Receiving Data Through a Socket

After a socket has been established, an application can transmit or receive data through the socket. The following socket functions are used in the transmission or receipt of data between sockets:

Closing the Connection

An application closes a connection when it has no more data to send. An application can also shut down transmissions in one or both directions. The following functions close the connection or shut down transmissions:

Copyright (c) 1998 SAS Institute Inc. Cary, NC, USA. All rights reserved.