一:打印机

1、Slice定义:

interface Printer

{

void printString(string s);

};

我们的Slice定义含有一个接口,叫作Printer。目前,我们的接口非常

简单,只提供了一个操作,叫作printString。该定义保存为Printer.ice

2、要创建我们的C++应用,第一步是要编译我们的Slice定义,生成C++代理和骨架。在UNIX上,你可以这样编译定义:

$ slice2cpp Printer.ice

slice2cpp编译器根据这个定义生成两个C++源文件:Printer.h和Printer.cpp。

Printer.h头文件含有与我们的Printer接口的Slice定义相对应的C++类型定义。在客户和服务器源码中必须包括这个头文件。

Printer.cpp文件含有我们的Printer接口的源码。所生成的源码同时为客户和服务器提供针对特定类型的运行时支持。例如,它包含了在客户端整编参数数据 (传给printString操作的串)的代码,以及在服务器端解编数据的代码。

3.server.cpp

#include <Ice/Ice.h> //Ice.h中包含了Ice run time的各种定义

#include <Printer.h> //生成的Printer.h

using namespace std;

class PrinterI : public Printer {

public:

//virtual C++定义虚函数的关键字

/*

*注意,printString有第二个参数,类型是Ice::Current。从Printer::printString的定 *义你可以看到,Slice编译器会为这个形参生成缺省的实参,所以在我们的实现中 *可以不使用它 (我们将在后面介绍)。

*/

virtual void printString(const string & s, const Ice::Current &);

};

/*

*Printer骨架类定义是由Slice编译器生成的 (注意,printString是纯虚方法,所以这个 *骨架类不能被实例化)。我们的servant类继承自骨架类,提供了printString纯虚方法 *的实现 (按照惯例,我们用I后缀表示这个类实现了一个接口)

*/

void  PrinterI::printString(const string & s, const Ice::Current &)

{

cout << s << endl;

}

int  main(int argc, char* argv[])

{

/*

*main的主体声明了两个变量status和ic。status变量含有程序的退出状态,而类型 *为Ice::Communicator的ic变量含有Ice run time的主句柄。

*/

int status = 0;

Ice::CommunicatorPtr ic;

/*

try{

程序执行错误,抛出异常

}catch(异常1){

捕捉try模块抛出的异常,如果是异常1的话进入此模块

}catch(异常2){

捕捉try模块抛出的异常,如果是异常2的话进入此模块

}

*/

try {

/*

*Ice::initialize,初始化Ice run time(我们之所以把argc和argv传给这个调用, *是因为服务器可能有run time感兴趣的命令行参数;就这个例子 而言,服*务器不需要任何命令行参数)。initialize调用返回的是一个智能指针,指向一*个Ice::Communicator对象,这个指针是Ice run time的主句柄。

*/

ic = Ice::initialize(argc, argv);

/*

*我们调用Communicator实例上的createObjectAdapterWithEndpoints,创建一 *个对象适配器。我们传入的参数是"SimplePrinterAdapter"(适配器的名字) *和"default -p 10000",后者是要适配器用缺省协议(TCP/IP)在端口10000 *处侦听到来的请求。

*/

Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints(

"SimplePrinterAdapter", "default -p 10000");

/*

*这时,服务器端run time已经初始化,我们实例化一个PrinterI对象,为我们 *的Printer接口创建一个servant。

*/

Ice::ObjectPtr object = new PrinterI;

/*

*我们调用适配器的add,告诉它有了一个新的servant;传给add的参数是我 *们刚才实例化的servant,再加上一个标识符。在这里,"SimplePrinter"串是 *servant的名字(如果我们有多个打印机,每个打印机都可以有不同的名字, *更正确的说法是,都有不同的对象标识)。

*/

adapter->add(object, Ice::stringToIdentity("SimplePrinter"));

/*

*接下来,我们调用适配器的activate方法激活适配器 (适配器一开始是在扣 *留(holding)状态创建的;这种做法在下面这样的情况下很有用:我们有多 *个servant,它们共享同一个适配器,而在所有servant实例化之前我们不想处 *理请求)。一旦适配器被激活,服务器就会开始处理来自客户的请求。

*/

adapter->activate();

/*

*最后,我们调用waitForShutdown。这个方法挂起发出调用的线程,直到服务 *器实现终止为止——或者是通过发出一个调用关闭run time,或者是对某个 *信号作出响应 (目前,当我们不再需要服务器时,我们会简单地在命令行上 *中断它)。

*/

ic->waitForShutdown();

} catch (const Ice::Exception & e) {

cerr << e << endl;

status = 1;

} catch (const char * msg) {

cerr << msg << endl;

status = 1;

}

if (ic)

ic->destroy(); //确保Ice run time得以执行结束工作(前提是通信器进行过初始化)

return status;

}

4.编译server.cpp

$ c++ -I. -I$ICE_HOME/include -c Printer.cpp Server.cpp

这条命令编译我们的应用代码,以及Slice编译器生成的代码。我们假定ICE_HOME环境变量被设成Ice run time所在的顶层目录 (例如,如果你把Ice安装在/opt/Ice中,就把ICE_HOME 设成该路径)。取决于你的平台,你可能需要给编译器增加额外的包括指令或其他选项 (比如增加包括STLport头的指令,或是对模板实例化进行控制);要了解详情,请参考随Ice发布的演示程序。

最后,我们需要把服务器链接成可执行程序:

$c++ -o server Printer.o Server.o  -L $ICE_HOME/lib -lIce -lIceUtil

取决于你的平台,你需要链接的库可能会更多。随Ice发布的演示程序含有所有的细节。在此,需要提及一个要点:Ice run time是在两个库中:libIce和libIceUtil。

6. client.cpp

#include <Ice/Ice.h>

#include <Printer.h>

using namespace std;

int  main(int argc, char * argv[])

{

int status = 0;

Ice::CommunicatorPtr ic;

try {

ic = Ice::initialize(argc, argv);

/*

*获取远地打印机的代理。我们调用通信器的stringToProxy创建一个代理,所 *用参数是"SimplePrinter:default -p 10000"。注意,这个串包含的是对象标识和 *服务器所用的端口号(显然,在应用中硬编码对象标识和端口号,是一种糟 *糕的做法,但它目前很有效;我们将在后面看到在架构上更加合理的做法)。 */

Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:default -p 10000");

/*

*stringToProxy返回的代理的类型是Ice::ObjectPrx,这种类型位于接口和类的 *继承树的根部。但要实际与我们的打印机交谈,我们需要的是Printer接口、 *而不是Object接口的代理。为此,我们需要调用PrinterPrx::checkedCast进行 *向下转换。这个方法会发送一条消息给服务器,实际询问 “这是Printer接 *口的代理吗?”如果是,这个调用就会返回Printer的一个代理;如果代理代 *表的是其他类型的接口,这个调用就会返回一个空代理。

*/

PrinterPrx printer = PrinterPrx::checkedCast(base);

/*我们测试向下转换是否成功,如果不成功,就抛出出错消息,终止客户。*/

if (!printer)

throw "Invalid proxy";

/*

*现在,我们在我们的地址空间里有了一个活的代理,可以调用printString方 *法,把享誉已久的 "Hello World!"串传给它。服务器会在它的终端上打印这 *个串。

*/

printer->printString("Hello World!");

} catch (const Ice::Exception & ex) {

cerr << ex << endl;

status = 1;

} catch (const char * msg) {

cerr << msg << endl;

status = 1;

}

if (ic)

ic->destroy();

return status;

}

ICE——1.Printer的更多相关文章

  1. ICE学习——异步1

    ICE的AMI和AMD: AMI:指的是客户端的调用.一般有一个代理类,一个回调类. 从服务端返回的数据在回调类中的ice_response函数中. AMD:指的是服务端对客户端的调用分派.一般进行业 ...

  2. ICE的异步方法调用

    转自:http://blog.sina.com.cn/s/blog_45497dfa0100nwbr.html http://www.cnblogs.com/mawanglin2008/article ...

  3. ubuntu安装ICE记录

    背景本文档介绍在unbuntu环境下如何安装ICE,并用C++写一个ICE应用 ICE简介ICE是ZEROC的开源通信协议产品,它的全称是:The Internet Communications En ...

  4. Ice分布式程序设计—IceBox(Hello World Application)

    忙了三天,总算浏览完此书.藉此记下 Ice 的 IceBox 服务框架. 在此用 IceBox 框架写 Hello World 程序,即以载体来体现其特性. 第一步:编写 Slice 文件,映射生成 ...

  5. Ice的HelloWorld(Java)

    Ice是一种面向对象的中间间平台,入门ice,简单的HelloWorld是必不可少的. 转载请注明http://www.cnblogs.com/zrtqsk/p/3745286.html,谢谢. 一. ...

  6. ICE学习第三步-----Slice语言

    ICE:Slice语言(一)-编译 Introduce简介 Slice(Specification language for ice)是分离对象和对象的实现的基础的抽象机制.Slice在客户端和服务器 ...

  7. ICE学习第二步-----从第一个程序了解ICE(HelloWorld)

    ICE(Internet Communications Engine)是一种面向对象的中间件平台,主要用于网络通讯.它为面向对象的“客户端-服务器”模型的应用提供了一组很好的工具和API接口.目前在全 ...

  8. ICE 介绍及实现

    .ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Internet Communications Engine,翻译为中文是互联网通信引擎,是一个面向对象的中间件,使我们能够 ...

  9. ICE之C/S通信原理

    /* 在ICE文档中只需要声明module名称,接口名称,方法名称 */ #ifndef SIMPLE_ICE #define SIMPLE_ICE module Demo{ //module名称 i ...

随机推荐

  1. 免费电子书:Azure Web Apps开发者入门

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:之前介绍过微软正在逐步出版一个名为Azure Essential的入门系列教程,最近刚 ...

  2. bbed的使用--查看数据文件信息 & sid信息

    1.得到文件的块大小和数据块个数 在Linux和Unix上,oracle提供了一个小工具dbfsize用于查看文件块大小 (可以参看[ID:360032.1]How to detect and fix ...

  3. Linux内核学习之道

    来自:http://blog.chinaunix.net/uid-26258259-id-3783679.html 内核文档 内核代码中包含有大量的文档,这些文档对于学习理解内核有着不可估量的价值,记 ...

  4. AES128和AES256主要区别和安全程度是多少?他们对于机器的消耗是怎样的?两者性能如何?实际开发如何选择?

    高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES, ...

  5. SQLserver删除某数据库中所有表 方法 二

    方便删除数据库中所有的数据表,清空数据库,有些有约束,不能直接delete,需要先删除库中的约束,代码如下: --删除所有约束DECLARE c1 cursor for select 'alter t ...

  6. 【js 方法】js 页面刷新location.reload和location.replace的区别 【转】

    [转]:http://zccst.iteye.com/blog/2162658 reload 方法,该方法强迫浏览器刷新当前页面. 语法: location.reload([bForceGet]) 参 ...

  7. 分享一个漂亮WPF界面框架创作过程及其源码(转)

    本文会作为一个系列,分为以下部分来介绍: (1)见识一下这个界面框架: (2)界面框架如何进行开发: (3)辅助开发支持:Demo.模板.VsPackage制作. 框架源码如下所示. 本文介绍第(1) ...

  8. C#根据html生成PDF

    使用iTextSharp 控件 iTextSharp包括几个dll. 主要iTextSharp版本包含:——itextsharp.dll:核心库——itextsharp.xtra.dll:额外的功能( ...

  9. 01_Java语言基础部分(数据类型与表达式、流程控制语句、数组与方法)

    1. Java语言主要由5中符号组成 标识符:数字.字母.美元符.下划线(注意不能数字开头) 关键字(被Java赋予特殊意义的单词,注意所有关键字都是小写):   goto和const保留了它们,但是 ...

  10. CSS3-html,样式与样式表的创建,选择器