RPC远程过程调用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南华大学
计算机科学与技术学院
实验报告
(2010~2011学年度第2学期)
课程名称分布式系统
题目RPC远程过程调用
一、实验目的
通过远程过程调用(RPC)的OSF以及如何使用它们来开发应用程序,了解RPC的基本原理,并认识如何开发使用RPC进行异种机网络分布式处理的客户机应用程序和服务器应用程序。实现一个简单的rpc远程过程调用程序,学会一些基本的rpc函数的使用方法
二、实验环境
操作系统:Windows 7
开发环境: Microsoft Visual C++
三、实验步骤
1. 定义接口:创建一个.idl文件, 为应用程序的远地函数定义一个接口.// File: RpcFact.idl
// interface header
uuid (C16F6562-520D-11D0-B338-444553540000), // universally unique identifier,唯一识别这个接口, 它可以被服务器用来注册接口, 以使客户机可以定位这个特殊接口. uuid由5位数字组成,你可以用Microsoft的uuidgen.exe来得到它.
version (1.0), // 指定版本号, 那么在同一个网络上就可以同时拥有一个R PC接口的不同版本
endpoint(“ncalrpc: [myFactorial]”) // 接口的端点, 它给出了将会使用的网络协议的类型和用来接收接口的请求的地址和端口, ncalrpc 表示Local pr ocedure call
// interface text, 指定了组成这个接口的函数, 函数类型不支持int 和void*
interface rpcfactor ial
{
long RpcFactor ial([in] long nVal); // 出现[ ]的部分表示属性
}
// end File RpcFact.idl
2. 应用程序属性配置文件
// RpcFact.acf
[ auto_handle // 相关属性]
interface rpcfactor ial{ }// end File RpcFact.acf
3. 用MIDL编译器编译RpcFact.idl文件
先将RpcFact.idl插入你的Project中, 在Projects—Settings中选取左边框内的RpcFact.idl文件, 选择右边的Custom Build页面, 位IDL文件指定一个用户定制的编译器. 可以键入如下命令:midl.exe /c_text /ms_text
/app_config $ (InputPath)
4. 开发RPC服务器
定义好了一个接口之后, 就需要创建一个响应接口请求的进程, 执行请求的操作并返回所有结果给client. 这些任务就由RPC服务器来完成.
(1) 执行计算的过程
// File: RpcFact.c
#include
#include “RpcFact.h” // 用MIDL编译器生成
long Factorial (long nVal)
{
long nResult = 1;
for (; nVal>0; nVal--)
nResult *= nVal;
return nResult;
}
// end File RpcFact.c
(2) RPC服务器实体
使RpcFact.c真正对RPC有用的工作是在服务器实体(RpcFact_s.c)中实现的. 实体内的代码负责建立RPC接口的捆绑, 并用名称服务程序来注册它们及侦听RPC请求. Server端也与RPC runtime连接. 不过server端应用程序使用一些其它的函数来将自己作为一个特殊接口的服务器进行注册(向谁注册?), 并开始侦听接口的请求.
// File: RpcFact_s.c
#include
#include
#include
#include “RpcFact.h”
#include “memstub.h”// 实现RPC函数的存储分配, 稍后介绍
main()
{
RPC_BINDING_VECTOR* bindVector;
RPC_STATUS lRetVal;
// 注册所有可行的协议序列, 所支持的协议由在RpcFact.idl的端点定义中的字符串指定
// 参数rpcf actorial_v1_0_s_ifspec定义在RpcFact.h中, 由MIDL编译生成
if (lRetVal = RpcServ erUseAllProtseqsIf(1, rpcfactorial_v1_0_s_ifspec, NULL))
{
cout<<”Error in RpcServ erUseAllProtseqsIf”< return 1; }// 注册所支持的接口 if (RpcServerRe Gis terIf(rpcfactorial_v1_0_s_ifspec, NULL, NULL)) { cout<<”Error in RpcServerRegister”< return 1; }// 将接口的捆绑输出到名称服务程序 if (RpcServerInqBindings(&bindVector)) { cout<<”Error in RpcServerInqBindings”< return 1;} if (RpcServerBindingExport(RPC_C_NS_SYNTAX_DEFAULT, (UCHAR*)”/.: /autorpc”, rpcfactorial_v1_0_s_ifspec, bindVector, NULL)) { cout<<”Error in RpcServerBidingExport”< return 1;}// 侦听RPC请求 cout<<”Calling RpcServerListen”< if (RpcServerListen(1, 5, FALSE)) { cout<<”Error in RpcServerListen”< return 1;} return 0; }// end main // end File RpcFact_s.c // File: memstub.h // 以下两个函数在RpcFact.h中已经声明 void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len) { return (new (unsigned char [len])); } void __RPC_USER M IDL_user_free( void __RPC_FAR* ptr) { delete ptr; }// end File memstub.h (3) 建立服务器 建立服务器时,需要确保连接server stub函数(即RpcFact_s.c)编译后的.obj文件. 此外还得添加两个RPC运行库(rpcns4.lib和rpcrt4.lib). 倾听状态, 等待client端发送过程调用消息; 一旦接收到过程调用消息, server 就抽取参数并分析它, 然后执行所请求的过程; 将执行结果以消息包形式回送给client. 5. RPC客户机: