RPC 服务器由一系列过程组成,客户端可以通过向服务器发送 RPC 请求以及过程参数来调用这些过程。服务器将代表客户端调用指定的程序,并返回返回值(如果有)。为了实现机器无关性,客户端和服务器之间交换的所有数据都由发送者转换为所谓的外部数据表示 (XDR) 格式,并由接收者转换回机器本地表示。
有时,对 RPC 应用程序的改进会在过程调用接口中引入不兼容的更改。当然,简单地更改服务器会使所有仍然期望原始行为的应用程序崩溃。因此,RPC 程序被分配了版本号,通常从 -1 开始,并且每次 RPC 接口的新版本发布时,此计数器都会递增。通常,服务器可能会同时提供多个版本;然后,客户端在其请求中通过版本号来指示他们想要使用的服务实现。
RPC 服务器和客户端之间的网络通信有点特殊。一个 RPC 服务器提供一个或多个过程的集合;每个集合都被称为一个程序,并通过一个程序号唯一标识。服务名称到程序号的映射列表通常保存在 /etc/rpc 中,其摘录在图 中再现。
在 TCP/IP 网络中,RPC 的作者面临着将程序号映射到通用网络服务的问题。他们选择让每个服务器为每个程序和每个版本提供 TCP 和 UDP 端口。通常,RPC 应用程序在发送数据时会使用 UDP,并且仅当要传输的数据不适合单个 UDP 数据报时才回退到 TCP。
当然,客户端程序必须有一种方法来找出程序号映射到哪个端口。为此使用配置文件会过于不灵活;由于 RPC 应用程序不使用保留端口,因此无法保证最初打算由我们的数据库应用程序使用的端口没有被其他进程占用。因此,RPC 应用程序选择它们可以获得的任何端口,并将其注册到所谓的端口映射器守护进程。后者充当在其机器上运行的所有 RPC 服务器的服务代理:希望联系具有给定程序号的服务的客户端将首先查询服务器主机上的端口映射器,端口映射器会返回可以访问该服务的 TCP 和 UDP 端口号。
这种方法有一个特殊的缺点,即它引入了单点故障,就像 inetd 守护进程对标准 Berkeley 服务所做的那样。然而,这种情况甚至更糟,因为当端口映射器死掉时,所有 RPC 端口信息都会丢失;这通常意味着您必须手动重启所有 RPC 服务器,或重启整个机器。
在 上,端口映射器被称为 rpc.portmap,并位于 /usr/sbin 中。除了确保它从 rc.inet2 启动之外,端口映射器不需要任何配置工作。