The general mechanism for client-server applications is provided by the
Remote Procedure Call (RPC) package. RPC was developed by Sun
Microsystems and is a collection of tools and library functions. Important
applications built on top of RPC are NIS, the Network Information System
(described in Chapter 13), and NFS, the Network File System
(described in Chapter 14), which are both described in
this book.
An RPC server consists of a collection of procedures that a client can call
by sending an RPC request to the server along with the procedure parameters.
The server will invoke the indicated procedure on behalf of the client,
handing back the return value, if there is any. In order to be
machine-independent, all data exchanged between client and server is
converted to the External Data Representation format
(XDR) by the sender, and converted back to the machine-local representation
by the receiver. RPC relies on standard UDP and TCP sockets to transport the
XDR formatted data to the remote host. Sun has graciously placed RPC in the
public domain; it is described in a series of RFCs.
Sometimes improvements to an RPC application introduce incompatible changes
in the procedure call interface. Of course, simply changing the server would
crash all applications that still expect the original behavior. Therefore,
RPC programs have version numbers assigned to them, usually starting with 1,
and with each new version of the RPC interface, this counter will be bumped up.
Often, a server may offer several versions simultaneously; clients then
indicate by the version number in their requests which implementation of
the service they want to use.
The communication between RPC servers and clients is somewhat peculiar. An
RPC server offers one or more collections of procedures; each set is called
a program and is uniquely identified by a
program number. A list that maps service names to program
numbers is usually kept in /etc/rpc, an excerpt of which
is shown in Example 12-4.
Example 12-4. A Sample /etc/rpc File
#
# /etc/rpc - miscellaneous RPC-based services
#
portmapper 100000 portmap sunrpc
rstatd 100001 rstat rstat_svc rup perfmeter
rusersd 100002 rusers
nfs 100003 nfsprog
ypserv 100004 ypprog
mountd 100005 mount showmount
ypbind 100007
walld 100008 rwall shutdown
yppasswdd 100009 yppasswd
bootparam 100026
ypupdated 100028 ypupdate |
In TCP/IP networks, the authors of RPC faced the problem of mapping
program numbers to generic network services. They designed each server to
provide both a TCP and a UDP port for each program and each version. Generally,
RPC applications use UDP when sending data, and fall back to TCP only
when the data to be transferred doesn't fit into a single UDP datagram.
Of course, client programs need to find out to which port
a program number maps. Using a configuration file for this would be
too unflexible; since RPC applications don't use reserved ports, there's
no guarantee that a port originally meant to be used by our database
application hasn't been taken by some other process. Therefore, RPC
applications pick any port they can get and register it with a special program
called the portmapper daemon. The portmapper acts as a
service broker for all RPC servers running on its machine. A client that
wishes to contact a service with a given program number first queries
the portmapper on the server's host, which returns the TCP and UDP port
numbers the service can be reached at.
This method introduces a single point of failure, much like the
inetd daemon does for the standard
Berkeley services. However, this case is even a little worse because
when the portmapper dies, all RPC port information is lost; this
usually means you have to restart all RPC servers manually or reboot
the entire machine.
On Linux, the portmapper is called /sbin/portmap, or
sometimes /usr/sbin/rpc.portmap. Other than making sure
it is started from your network boot scripts, the portmapper doesn't require
any configuration.