第一章 TxRPC简介
什么是TxRPC
TxRPC允许程序员使用远程过程调用(RPC)接口,一个客户进程可以使用本地函数调用另一个进程中的过程(也就是远程服务)。程序员必须通过接口定义语言IDL明确规定过程及数据类型。IDL编译器用于生成成两个代理。当客户程序调用IDL文件中定义的函数时,它并未直接调用它,而是调用驻留在客户机上的stub代理,客户stub接收输入参数,并把它们转换成单个缓冲区,然后把它发送到服务器,等待响应。远程过程处理完毕后,以缓冲区形式进行响应,客户程序从中取出返回值和输出参数。客户进程和服务器进程之间的通信,不论是同一台机器内部还是跨越了多台机器,都由Tuxedo系统运行时来处理。
在服务器端,运行时调用服务器端代理stub。服务器代理把客户代理发送来的数据解包,取出输入参数,调用服务,等待响应结果。远程过程执行完毕后,服务器stub将返回值和输出参数放入缓冲区,发送回客户stub。从应用程序的角度来看,就好象简单地调用了一个本地方法一样。stubs和运行时把对远程过程的调用隐藏到一个非本地地址空间中。
构建一个RPC应用程序和构建一个普通应用程序步骤相同,大部分时间都用在写客户程序和服务器程序上。Tuxedo运行时系统使用程序不必关心网络通信,以及如何将客户机使用的数据翻译成服务器上使用的类型等。TxRPC也可以用于服务器之间的通信。
必须做的工作是定义客户机和服务器之间的接口格式,也就是编制IDL文件。IDL文件中包含了数据类型和调用远程过程使用的操作。IDL文件扩展名为.idl。它个接口都必须在它自己的唯一标识——全球唯一标识UUID,它由128bits构成,唯一标识着一个接口,可以通过UUIDGEN来生成。-i指示生成一个接口文件。UUID在运行时用于确保客户机stub和服务器stub相匹配。除了UUID以外,第个接口还有一个版本号,如果版本号没有作为接口的一部分指定,缺省为0.0。因此,同一个接口可以有多个版本。客户机总是请求与自己版本号相同的服务器。不同版本意味着输入参数、返回值可能不同,而且某些操作可能已经从接口中删除了。因此,RPC要成功,客户机的版本号必须和服务器的版本号匹配。用uuidgen生成一个IDL的模板后,程序员需要往里面加入数据类型及操作。IDL语法和C++语法相似。数据类型通过typedef定义,操作通过函数的原型说明来声明。其它信息通过IDL
属性提供。属性出现在方括号里,如[in],它可以提供诸如打印机等信息。对于参数,需要指明参数是input, output, 还是两者都是。
除了IDL文件外,一个可选的属性配置文件ACF也可以用于为接口提供其它属性。ACF中的变量不影响客户和服务器之间的通信,但对应用程序代码和生成的stubs之间的接口有一个总体的影响。
使用Tuxedo的运行时,客户和服务器之间的绑定是透明的,不需要为它们提供任何信息,而在使用OSF DCE运行时,程序员必须花费很大的精力来解决绑定管理。由于BEA Tuxedo不支持OSF DCE运行时函数,因此,绑定属性在IDL和ACF文件中被忽略了。
IDL和ACF文件都用IDL编译器进行编译。编译器先生成一个头文件,它包含了IDL文件中定义的所有类型和函数原型说明。如果输入文件是file.idl和file.acf,则生成的头文件为file.h,stub文件为:file_cstub.c和file_sstub.c。stub文件在RPC通信中用于打包和通信。编译器一般直接将它们编译成.obj文件,而把源文件.c删除。
完成接口定义之后,主要的工作是编写应用程序代码了。客户机要调用接口中定义的函数,服务器必须实现接口中定义的操作。当编码完成后,需要将它们和BEA Tuxedo的运行库进行编译连接,两个程序可以用过简化整个过程:buildserver建立服务器程序,buildclient用于建立客户程序,建立服务器过程如下图所示:
1. 运行UUIDGEN生成IDL文件的框架(simp.idl,具有UUID)。编辑IDL文件,定义客
户和服务器之间的接口。 2. 运行IDL编译器tidl,以simp.idl和simp.acf作为输入文件,创建接口头文件simp.h和
服务器、客户机目标文件simp_sstub.obj, simp_cstub.obj。
3. 写完服务器程序server.c后,运行buildserver编译它,并将它和服务器stub文件、BEA Tuxedo运行时库进行连接,生成server.exe。 建立客户机的过程如下图所示:
4. 使用1中创建的IDL文件,运行IDL编译器tidl,生成接口头文件和客户机stub。 5. 运行buildclient,把client.c和stub文件,头文件,BEA Tuxedo运行时库,TxRPC运行
时库进行连接,生成client.exe。
第二章 使用接口定义语言IDL
§2.1 使用uuidgen创建IDL模板
UUID用于唯一标识一个接口,uuidgen命令用于生成UUID。生成过程如下: $ uuidgen -i > simp.idl
$ cat simp.idl
[uuid(C996A680-9FC2-110F-9AEF-930269370000)] interface INTERFACE {
}
编辑simp.idl文件,将接口名改为changecase,并添加两个函数的原型说明: [uuid(C996A680-9FC2-110F-9AEF-930269370000), version(1.0) ] interface changecase {
void to_upper([in, out, string] char *str); void to_lower([in, out, string] char *str); }
§2.2 使用IDL编译器tidl
在兼容性方面,tidl和DCE的idl有很多相似的地方,但也存在一些不同,如;DCE中用的是idl,BEA Tuxedo使用tidl。
第三章 编写RPC客户和服务器程序
§3.1 处理过程
TxRPC的目的就是在客户机和服务器之间提供一个透明的过程调用,由于与客户机与服务器不在同一进程空间,所以存在如下一些问题:
1. 由于客户机和服务器可能在不同的机器上,所以不能使用共享内存,全局变量就不可用
了,状态信息需要由客户端传给服务器端,然后再传回来。 2. 把客户端和服务器开发工作分开有一些优点,如更加模块化。但是却带来了一些复杂性,
如分布式处理,通信问题等。
§3.2 处理状态和例外
在X/OPEN RPC规范中,非应用程序错误通过状态参数返回,如果有一个RPC服务器
相关推荐: