分享
 
 
 

RPC远程过程调用实例剖析之二

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

RPC远程过程调用实例剖析之二

paddy102

Para4. 一个计算阶层的RPC实例开发过程

Microsoft提供了分布式计算的模型支持. RPC标准最初是作为OSF(开放软件基础)﹑DCE(分布式计算环境)规范的一部分. RPC的Microsoft实现与其它的RPC的DCE实现兼容, 例如UNIX服务器. 本节将介绍RPC的Microsoft实现. 文中涉及的一些概念如IDL(interface definition language)等请朋友们自己查找资料理解.

本程序由以下几个文件组成:

RpcFact.idl

RpcFact.acf

RpcFact.h

RpcFact_c.c

RpcFact_s.c

RpcFact.c

memstub.h

下面结合实现原理一一道来:

1. 定义接口 (得到RpcFact.idl文件)

创建一个.idl文件, 为应用程序的远地函数定义一个接口.

// File: RpcFact.idl

// interface header

[

uuid (C16F6562-520D-11D0-B338-444553540000), // universally unique identifier,唯一识别这个接// 口, 它可以被服务器用来注册接口, 以使客户机可以定位这个特殊接口. uuid由5位数字组

// 成,你可以用Microsoft的uuidgen.exe来得到它.

version (1.0), // 指定版本号, 那么在同一个网络上就可以同时拥有一个RPC接口的不同版本

endpoint(“ncalrpc: [myFactorial]”) // 接口的端点, 它给出了将会使用的网络协议的类型和用来接

// 收接口的请求的地址和端口, ncalrpc 表示Local procedure call

]

// interface text, 指定了组成这个接口的函数, 函数类型不支持int 和void*

interface rpcfactorial

{

long RpcFactorial([in] long nVal); // 出现[ ]的部分表示属性

}

// end File RpcFact.idl

2. 应用程序属性配置文件 (得到RpcFact.acf文件)

.acf文件用来指定应用程序的选项, 这些属性告诉client stub如何对接口请求的捆绑进行处理, 这个问题稍后介绍.

// RpcFact.acf

[

auto_handle // 相关属性

]

interface rpcfactorial

{

}

// end File RpcFact.acf

3. 用MIDL编译器编译RpcFact.idl文件

第一种方式, midl.exe /c_text /ms_text /app_config RpcFact.idl (详细了解请在dos下运行midl.exe /?获取).

第二种方式, 先将RpcFact.idl插入你的Project中, 在Projects—Settings中选取左边框内的RpcFact.idl文件, 选择右边的Custom Build页面, 位IDL文件指定一个用户定制的编译器. 可以键入如下命令:

midl.exe /c_text /ms_text /app_config $ (InputPath)

经过编译之后, 会生成这几个文件: RpcFact.h、RpcFact_s.c 和RpcFact_c.c

4. 开发RPC服务器

定义好了一个接口之后, 就需要创建一个响应接口请求的进程, 执行请求的操作并返回所有结果给client. 这些任务就由RPC服务器来完成.

(1) 执行计算的过程

本例中就是阶层函数的实现, 我把它单独放在一个RpcFact.c文件中.

// File: RpcFact.c

#include <windows.h>

#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请求.

// File: RpcFact_s.c

#include <windows.h>

#include <iostream.h>

#include <rpc.h>

#include “RpcFact.h”

#include “memstub.h” // 实现RPC函数的存储分配, 稍后介绍

main()

{

RPC_BINDING_VECTOR* bindVector;

RPC_STATUS lRetVal;

// 注册所有可行的协议序列, 所支持的协议由在RpcFact.idl的端点定义中的字符串指定

// 参数rpcfactorial_v1_0_s_ifspec定义在RpcFact.h中, 由MIDL编译生成

if (lRetVal = RpcServerUseAllProtseqsIf(1, rpcfactorial_v1_0_s_ifspec, NULL))

{

cout<<”Error in RpcServerUseAllProtseqsIf”<<lRetVal<<endl;

return 1;

}

// 注册所支持的接口

if (RpcServerRegisterIf(rpcfactorial_v1_0_s_ifspec, NULL, NULL))

{

cout<<”Error in RpcServerRegister”<<endl;

return 1;

}

// 将接口的捆绑输出到名称服务程序

if (RpcServerInqBindings(&bindVector))

{

cout<<”Error in RpcServerInqBindings”<<endl;

return 1;

}

if (RpcServerBindingExport(RPC_C_NS_SYNTAX_DEFAULT, (UCHAR*)”/.: /autorpc”, rpcfactorial_v1_0_s_ifspec, bindVector, NULL))

{

cout<<”Error in RpcServerBidingExport”<<endl;

return 1;

}

// 侦听RPC请求

cout<<”Calling RpcServerListen”<<endl;

if (RpcServerListen(1, 5, FALSE))

{

cout<<”Error in RpcServerListen”<<endl;

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 MIDL_user_free( void __RPC_FAR* ptr)

{

delete ptr;

}

// end File memstub.h

(3) 建立服务器

建立服务器时, 你需要确保连接server stub函数(即RpcFact_s.c)编译后的.obj文件. 此外还得添加两个RPC运行库(rpcns4.lib和rpcrt4.lib).

5. 开发RPC客户机

// File: RpcFact_c.c

#include <windows.h>

#include <iostream.h>

#include <rpc.h>

#include <stdlib.h>

#include “RpcFact.h”

#include “memstub.h”

main()

{

long nVal;

cout<<”Calling RPC Factorial”<<endl;

nVal = RpcFactorial(5);

cout<<”RpcFact returns: “<<nVal<<endl;

return 0;

}

// end File RpcFact_c.c

至此, 一个简单的RPC调用示例已经完成, 文中没讲清楚的地方请参看[1][2][3]列出的书籍, 或者你也可以与我联系.

本文的后续篇将继续介绍RPC中的参数传递﹑捆绑到RPC服务器的几种方式以及RPC的异常处理.

参考书籍:

[1] David Bennett等著. <<Visual C++ 5开发人员指南>>. 机械工业出版社

[2] <<分布式操作系统>>

[3] MSDN 6.0

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有