Remote Procedure Call 是一种=软件通信协议=,程序可以在不了解网络细节的前提下,向位于网络上的另外一台计算机中的本地程序请求服务。PRC 被用来像本地系统一样调用远程系统上的其他进程。
RPC 是通过 Interface Definition Language (IDL) 来描述接口,使得在不同的平台上运行的不同程序编写的程序可以相互通信。(IDL 是不以任何一种特定编程语言的方式指定类型签名或者函数调用的语言。)
基本上,你可以用 IDL 定义客户端和服务端之间的接口,这样 RPC 机制就可以创建跨网络调用功能所需要的代码存根(Code Stub)。
+----------------+
| Client |
| +----------+ | +---------------+
| | main | | | Server |
| |----------| | | +----------+ |
| | stub_cli |----(comms)--->| stub_svr | |
| +----------+ | | |----------| |
+----------------+ | | function | |
| +----------+ |
+---------------+
在这个例子中,main 没有在同一个程序中调用函数,而是调用了一个客户端存根函数(与函数的原型相同),该函数负责将信息打包,并通过通讯通道将其传送给另一个进程。
这里可以是同一台机器或者不同机器,RPC 的优势之一就是能够随意移动服务器。
在服务器中,有个「监听者」进程,它将接收这些信息并将其传递给服务器。服务器的存根接收信息,解包并将其传递给真正执行的函数。
真正的函数运行后返回结果给到服务器存根,服务器存根可以将返回的信息打包,并将其传回给客户端存根。客户端存根再将其解包并传回给 main。
实际上的 IDL 大概像下面这样:
[ uuid(f9f6be21-fd32-5577-8f2d-0800132bd567),
version(0),
endpoint("ncadg_ip_udp:[1234]", "dds:[19]")
] interface function_iface {
[idempotent] void function(
[in] int handle,
[out] int *status
);
}
头部是一些用于链接客户端和服务端的网络信息,RPC 发生在「会话层」中。接口部分才是 IDL 编译器建立客户端和服务器端存根的地方,以便客户端和服务端能够进行通讯,使得 RPC 正常工作。