Application Programming Interface API

An Application Programming Interface (API) defines how programmers utilize a particular computer feature. APIs exist for windowing systems, file systems, database systems, and, of course, networking systems. For the UNIX-based Internet programmer, three major APIs are of interest: Berkeley Sockets, System V TLI, and RPC. Sockets and TLI provide pretty much the same functionality (access to TCP and UDP) and are mutually exclusive, though it is possible to write conditionally-compiled code to support either. RPC's API (the RPC Language) supports network subroutines using Sun's RPC protocol. Microsoft Windows offers a Sockets-like API.

The API summaries that follow are just that - summaries.

Berkeley Sockets

Sockets is the original networking interface, developed by UCB for their BSD-series UNIX operating systems. A socket is a network communications endpoint, created mainly by the socket() function, which takes two key arguments - domain and type. The only domain we are interested in is Internet, or PF_INET, though other domains exist. There are two primary types of Internet sockets - STREAM (TCP) and DGRAM (UDP), which behave in different ways.

For UDP communications, connectionless by nature, DGRAM sockets are needed. Once created, a DGRAM socket can immediately be used to transmit UDP packets, using the sendto() function. To receive UDP packets as well, the socket must be attached to a local port address, using the bind() function. After binding a DGRAM socket to a UDP port address, it can be used for either transmission (with sendto()) or reception (with recvfrom()).

For TCP communications, connection-oriented by nature, STREAM sockets are needed. A STREAM socket can not send or receive data until a connection has been established. One way to establish a connection is to use the connect() function to specify a foreign TCP/IP port address and initiate a TCP connection, creating an active socket. The other way to establish a connection is to use the bind() and listen() functions to await an incoming TCP connection, creating a passive socket. Once an incoming TCP connection has been detected, the accept() call creates an active socket, ready for two-way communication. For most purposes, active TCP sockets behave just like UNIX file descriptors, and can be used by the read(), write(), and close() functions. Since TCP connections are identified by the IP addresses and port numbers of both endpoints, multiple TCP connections can exist on a single port, so long as each connection is paired with a unique foreign port. In terms of sockets, this means that multiple active sockets can be created from a single passive socket.

Most socket implementations provide library routines to perform DNS lookups to convert hostnames into IP addresses (Sun's NIS being the only major exception). The gethostbyname() function provides the main programming interface. The behavior of this function is typically configured by the /etc/resolv.conf file, which specifies a list of nameservers and the local default domain. Non-UNIX systems have other ways of configuring DNS behavior. Gethostbyname() will block until an answer is received or a timeout occurs, and is notorious for causing long delays when there are nameserver problems.

Although this discussion has been C-oriented, it is worth mentioning that Sockets has been successfully ported to other language environments, of which Perl is the most notable for UNIX systems.

System V TLI

System V's Transport Layer Interface (TLI) provides nearly identical functionality as Berkeley sockets. Fortunately, since both use standard Internet protocols, a TLI application can interact with a Sockets server, and vice versa.

The t_open function creates a transport endpoint, which can be manipulated with functions such as t_bind, t_connect, t_snd and t_rcv, which are analogous to their Sockets counterparts, except for their differing syntax. Normal UNIX file operations can also be used on open transport endpoints.

  • \begin{soapbox}

    TLI's main claim to superiority is its support for OSI, but there seems no compelling reason why Sockets couldn't also operate in an OSI environment, if anyone really wanted it to do so. AT&T's desire for a more proprietary networking interface is probably the real driving force behind TLI. Berkeley Sockets remains the API of choice for almost all UNIX-based Internet code.


RPC Language

The RPC Language enables a programmer to define the functional interface to an RPC program, then compile this into several C files using the rpcgen program. One of these files in a server shell. Code can be added to this shell to perform the desired functions. The server shell is then compiled to get a working server. Another of these files is a set of client stubs, which can be compiled into a client program to perform network RPC operations whenever one of the functions is invoked. In this manner, transparent RPC services can be constructed with relative ease.

A major drawback of the method described above is the inability to re-create the server shell after it has been modified. This problem can be circumvented by using rpcgen's ability to conditionally include escaped C code in the original source. What can I say? RTFM.

Microsoft Windows

Microsoft Windows supports a Sockets-like programming interface, but emphasizes event-based, non-blocking code, to provide constant handling of GUI events. Since the average UNIX Sockets program will block in several places (such as DNS lookups, or opening a TCP connection, or reading from one), porting network software to Microsoft Windows usually requires some code modification.

Windows will notify a program of network events by posting a user-defined event to a user-defined window. One way to handle this is to create an invisible window for each network connection, and define event handlers for things like key presses that will never occur normally in such a window. The window ID and key press event code are then passed to the networking library for event notification.

Vadim avatar