ICE 基础入门个人整理资料.docx

上传人:b****3 文档编号:11116417 上传时间:2023-05-29 格式:DOCX 页数:33 大小:27.81KB
下载 相关 举报
ICE 基础入门个人整理资料.docx_第1页
第1页 / 共33页
ICE 基础入门个人整理资料.docx_第2页
第2页 / 共33页
ICE 基础入门个人整理资料.docx_第3页
第3页 / 共33页
ICE 基础入门个人整理资料.docx_第4页
第4页 / 共33页
ICE 基础入门个人整理资料.docx_第5页
第5页 / 共33页
ICE 基础入门个人整理资料.docx_第6页
第6页 / 共33页
ICE 基础入门个人整理资料.docx_第7页
第7页 / 共33页
ICE 基础入门个人整理资料.docx_第8页
第8页 / 共33页
ICE 基础入门个人整理资料.docx_第9页
第9页 / 共33页
ICE 基础入门个人整理资料.docx_第10页
第10页 / 共33页
ICE 基础入门个人整理资料.docx_第11页
第11页 / 共33页
ICE 基础入门个人整理资料.docx_第12页
第12页 / 共33页
ICE 基础入门个人整理资料.docx_第13页
第13页 / 共33页
ICE 基础入门个人整理资料.docx_第14页
第14页 / 共33页
ICE 基础入门个人整理资料.docx_第15页
第15页 / 共33页
ICE 基础入门个人整理资料.docx_第16页
第16页 / 共33页
ICE 基础入门个人整理资料.docx_第17页
第17页 / 共33页
ICE 基础入门个人整理资料.docx_第18页
第18页 / 共33页
ICE 基础入门个人整理资料.docx_第19页
第19页 / 共33页
ICE 基础入门个人整理资料.docx_第20页
第20页 / 共33页
亲,该文档总共33页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

ICE 基础入门个人整理资料.docx

《ICE 基础入门个人整理资料.docx》由会员分享,可在线阅读,更多相关《ICE 基础入门个人整理资料.docx(33页珍藏版)》请在冰点文库上搜索。

ICE 基础入门个人整理资料.docx

ICE基础入门个人整理资料

ICE基础入门个人整理资料

ICE自定义了一种Slice语言,目的是定义接口,作用主要应该是保持对象调用或者数据传输时的语言无关性。

开发一个ICE应用程序可以分为三步:

1.写一个Slice定义,并且编译它

2.写服务端,并编译它

3.写客户端,并编译它

1.写一个Slice定义,并且编译它:

文件Printer.ice. 

moduleDemo{

interfacePrinter{

voidprintString(strings);

};

};

这个文件很简单,但需要注意,在区分大小写的系统上,扩展名一定是小写.

编译也很简单,首先确认你已将你的bin目录加到系统的环境变量Path中.然后把上面这个片断保存成Printer.ice,最后执行slice2cppPrinter.ice,执行后的结果应该是自动生成了printer.h和printer.cpp.

2.写服务端,并编译它

文件server.cpp. 

#include

#include"../print.h"

usingnamespacestd;

usingnamespaceDemo;

classPrinterI:

publicPrinter{

public:

virtualvoidprintString(conststring&s,constIce:

:

Current&);

};

voidPrinterI:

:

printString(conststring&s,constIce:

:

Current&)

{

cout<

}

intmain(intargc,char*argv[])

{

intstatus=0;

Ice:

:

CommunicatorPtric;

try{

ic=Ice:

:

initialize(argc,argv);

Ice:

:

ObjectAdapterPtradapter

=ic->createObjectAdapterWithEndpoints(

"SimplePrinterAdapter","default-p10000");

Ice:

:

ObjectPtrobject=newPrinterI;

adapter->add(object,

Ice:

:

stringToIdentity("SimplePrinter"));

adapter->activate();

ic->waitForShutdown();

}catch(constIce:

:

Exception&e){

cerr<

status=1;

}catch(constchar*msg){

cerr<

status=1;

}

if(ic){

try{

ic->destroy();

}catch(constIce:

:

Exception&e){

cerr<

status=1;

}

}

returnstatus;

}

以VS2003的配置为例

1.把ice的include加入VC7.1的引用文件目录,把ice的lib目录加入VC7.1的库文件目录。

然后再把安装目录下的bin文件夹添加到系统的环境变量Path中,最后,把bin文件夹下的所有DLL文件都Copy到Windows安装目录下的System32文件夹下(win98下是System文件夹?

)(当然,DLL文件的问题也可以通过修改环境变量来解决,不过是那个变量呢?

Whocantellme?

2.新建一个C++的Win32的命令台控制程序,并且设置为空项目,把server.cpp,printer.cpp和printer.h加入这个项目(printer.cpp和printer.h放在项目的目录的外一层目录)

3.项目-》属性-》C/C++-》代码生成-》运行时库-》/MD(realse版)或/MDd(debug版)

项目-》配置属性-》C/C++-》语言-》启用运行时类型信息/GR开启

设置:

项目-》属性-》链接器-》输入-》加入iced.libiceutild.lib,此处一定要把realse库和debug库分清,debug库后有个d

4.修改printer.cpp中的#include为#include"printer.h"

5.OK,编译

3.写客户端,并编译它

文件client.cpp. 

#include

#include"../print.h"

usingnamespacestd;

usingnamespaceDemo;

intmain(intargc,char*argv[])

{

intstatus=0;

Ice:

:

CommunicatorPtric;

try{

ic=Ice:

:

initialize(argc,argv);

Ice:

:

ObjectPrxbase=ic->stringToProxy(

"SimplePrinter:

default-p10000");

PrinterPrxprinter=PrinterPrx:

:

checkedCast(base);

if(!

printer)

throw"Invalidproxy";

printer->printString("HelloWorld!

");

}catch(constIce:

:

Exception&ex){

cerr<

status=1;

}catch(constchar*msg){

cerr<

status=1;

}

if(ic)

ic->destroy();

returnstatus;

}

添加一个新项目到当前解决方案,按照上面的方法,对client再一次进行设置。

在解决方案管理器的解决方案上点击右键,选择批生成Debug版本,然到用资源管理器到两个解决方案的目录下的Debug文件夹中执行生产的可执行文件。

先运行server.exe,然后运行client.exe,哈哈,是不是在server.exe的窗口里出现了HelloWorld!

(运行一次client.exe,出现一条)

 

初读代码

这一节大部分内容整理自ICE中文手册,在这里我特别感谢马维达同志的翻译给我们的学习带来了方便。

读服务端代码

文件server.cpp. 

#include

#include"../print.h"

usingnamespacestd;

usingnamespaceDemo;

//惯例,用后缀I表示这个类实现一个接口

classPrinterI:

publicPrinter{

public:

virtualvoidprintString(conststring&s,constIce:

:

Current&);

};

/*

打开print.h,看看PrinterI父类的定义

namespaceDemo{

classPrinter:

virtualpublicIce:

:

Object{

public:

//纯虚函数,不能实例化

virtualvoidprintString(conststd:

:

string&,

//第二个参数有缺省值,实现中可以不使用

constIce:

:

Current&=Ice:

:

Current())=0;

};

};

*/

voidPrinterI:

:

printString(conststring&s,constIce:

:

Current&)

{

cout<

}

intmain(intargc,char*argv[])

{

//程序的退出时的状态,就是否成功执行

intstatus=0;

//来包含Iceruntime的主句柄(mainhandle)

Ice:

:

CommunicatorPtric;

try{

//初始化Iceruntime(argc和argv是runtime命令参数;

//就这个例子而言,服务器不需要任何命令行参数)。

//initialize返回一个指向Ice:

:

Communicator对象的智能指针,

//这个指针是Iceruntime的主句柄。

ic=Ice:

:

initialize(argc,argv);

//调用Communicator实例上的createObjectAdapterWithEndpoints,

//创建一个对象适配器(比如:

网卡就是一种适配器)。

//参数是"SimplePrinterAdapter"(适配器的名字)

//和"default-p10000"(用缺省协议(TCP/IP),侦听端口10000的请求。

//显然,在应用中硬编码对象标识和端口号,是一种糟糕的做法,

//但它目前很有效;我们将在以后看到在架构上更加合理的做法。

Ice:

:

ObjectAdapterPtradapter

=ic->createObjectAdapterWithEndpoints(

"SimplePrinterAdapter","default-p10000");

//服务器端runtime已经初始化,实例化一个PrinterI对象,

//为我们的Printer接口创建一个servant(serv服务+-ant人,背一下单词)。

Ice:

:

ObjectPtrobject=newPrinterI;

//我们调用适配器的add,告诉它有了一个新的servant;

//传给add的参数是刚才实例化的servant,再加上一个标识符。

//在这里,"SimplePrinter"串是servant的名字

//(如果我们有多个打印机,每个打印机都可以有不同的名字,

//更正确的说法是,都有不同的对象标识)。

adapter->add(object,

Ice:

:

stringToIdentity("SimplePrinter"));

//调用适配器的activate方法激活适配器

//(适配器一开始是在暂停(holding)状态创建的;

//这种做法在下面这样的情况下很有用:

//我们有多个servant,它们共享同一个适配器,

//而在所有servant实例化之前我们不想处理请求)。

//一旦适配器被激活,服务器就会开始处理来自客户的请求。

adapter->activate();

//最后,我们调用waitForShutdown。

//这个方法挂起发出调用的线程直到服务器实现终止

//——或者是通过发出一个调用关闭runtime,

ic->waitForShutdown();

}

catch(constIce:

:

Exception&e){

cerr<

status=1;

}catch(constchar*msg){

cerr<

status=1;

}

if(ic){

try{

//必须调用Communicator:

:

destroy结束Iceruntime。

//destroy会等待任何还在运行的操作调用完成。

//此外,destroy还会确保任何还未完成的线程都得以汇合(joined),

//并收回一些操作系统资源,比如文件描述符和内存。

//决不要让你的main函数不调用destroy就终止,

//否则,后果无法想象。

ic->destroy();

}catch(constIce:

:

Exception&e){

cerr<

status=1;

}

}

returnstatus;

}

注意,尽管以上的代码不算少,但它们对所有的服务器都是一样的。

你可以把这些代码放在一个辅助类里,然后就无需再为它费心了(Ice提供了这样的辅助类,叫作Ice:

:

Application,参见10.3.1节)。

就实际的应用代码而言,服务器只有几行代码:

六行代码定义PrinterI类,再加上三2行代码实例化一个PrinterI对象,并向对象适配器注册它。

读客户端代码

文件client.cpp. 

#include

#include"../print.h"

usingnamespacestd;

usingnamespaceDemo;

intmain(intargc,char*argv[])

{

intstatus=0;

Ice:

:

CommunicatorPtric;

try{

ic=Ice:

:

initialize(argc,argv);

//stringToProxy返回的代理(Proxy)类型是Ice:

:

ObjectPrx,

//这种类型位于接口和类的继承树的根部(接口的基类)。

Ice:

:

ObjectPrxbase

=ic->stringToProxy("SimplePrinter:

default-p10000");

//但要实际要与我们的打印机交谈,

//我们需要的是Printer接口、不是Object接口的代理。

//为此,需要调用PrinterPrx:

:

checkedCast进行向下转换(向下转型)。

//这个方法会发送一条消息给服务器,

//询问“这是Printer接口的代理吗?

//如果回答“是”,就会返回Printer的一个代理;

//如果代理代表的是其他类型的接口,返回一个空代理

PrinterPrxprinter=PrinterPrx:

:

checkedCast(base);

//测试向下转型是否成功,若不成功,就抛出出错消息并终止客户。

if(!

printer)throw"Invalidproxy";

//现在,我们在我们的地址空间里有了一个激活的代理,

//可以调用printString方法,

//把享誉已久的"HelloWorld!

"串传给它。

//服务器会在它的终端上打印这个串。

printer->printString("HelloWorld!

");

}

catch(constIce:

:

Exception&ex){

cerr<

status=1;

}catch(constchar*msg){

cerr<

status=1;

}

if(ic)

ic->destroy();

returnstatus;

}

如果出现任何错误,客户会打印一条出错消息。

例如,如果我们没有先启动服务器就运行客户,我们会得到:

Network.cpp:

471:

Ice:

:

ConnectFailedException:

connectfailed:

Connectionrefused

(由于windows下的命令行窗口在出错后会一闪就消失,不过我们可以在client.cpp的main函数的returnstatus;之前加上system("PAUSE");然后再在VS中把client设置为启动项目,重新编译,运行。

OK,可以看到结果了。

 

 

Slice语言

首先,请大家读ICE中文手册中的Slice语言一章。

这一部分除了model(模块),在ICE1.3中文手册中都有描述

图 2.1. ice网络编程示意图(服务器端和客户端采用同种编程语言C++)

图 2.2. ice网络编程示意图(服务器端和客户端采用不同编程语言)

基础知识

含有Slice定义的文件必须以.ice扩展名结尾,例如,Clock.ice就是一个有效的文件名。

编译器拒绝接受其他扩展名。

Slice支持#ifndef、#define、#endif,以及#include预处理指令。

它们的使用方式有严格的限制:

你只能把#ifndef、#define,以及#endif指令用于创建双包括(double-include)块。

例如:

#ifndef_CLOCK_ICE

#define_CLOCK_ICE

//#include文件here...

//定义here...

#endif_CLOCK_ICE

我们强烈建议你在所有的Slice定义中使用双包括(double-include)块(所上),防止多次包括同一文件。

#include指令只能出现在Slice源文件的开头,也就是说,它们必须出现在其他所有Slice定义的前面。

此外,在使用#include指令时,只允许使用<>语法来指定文件名,不能使用""。

例如:

#include//OK

#include"File2.ice"//不支持!

你不能把这些预处理指令用于其他目的,也不能使用其他的C++预处理指令(比如用/字符来连接行、token粘贴,以及宏展开,等等)。

在Slice定义里,既可以使用C的、也可以使用C++的注释风格:

Slice关键字必须小写。

例如,class和dictionary都是关键字,必须按照所示方式拼写。

这个规则有两个例外:

Object和LocalObject也是关键字,必须按照所示方式让首字母大写。

标识符以一个字母起头,后面可以跟任意数目的字母或数字。

Slice标识符被限制在ASCII字符范围内,不能包含非英语字母,与C++标识符不同,Slice标识符不能有下划线。

这种限制初看上去显得很苛刻,但却是必要的:

保留下划线,各种语言映射就获得了一个名字空间,不会与合法的Slice标识符发生冲突。

于是,这个名字空间可用于存放从Slice标识符派生的原生语言标识符,而不用担心其他合法的Slice标识符会碰巧与之相同,从而发生冲突。

标识符(变量名等等)是大小写不敏感的,但大小写的拼写方式必须保持一致(看了后面的话,再理解一下)。

例如,在一个作用域内,TimeOfDay和TIMEOFDAY被认为是同一个标识符。

但是,Slice要求你保持大小写的一致性。

在你引入了一个标识符之后,你必须始终一致地拼写它的大写和小写字母;否则,编译器就会将其视为非法而加以拒绝。

这条规则之所以存在,是要让Slice既能映射到忽略标识符大小写的语言,又能映射到把大小写不同的标识符当作不同标识符的语言。

(可以这样理解,变量名区分大小写,并且不可以是相同的单词)

是关键字的标识符:

你可以定义在一种或多种实现语言中是关键字的Slice标识符。

例如,switch是完全合法的Slice标识符,但也是C++和Java的关键字。

语言映射定义了一些规则来处理这样的标识符。

要解决这个问题,通常要用一个前缀来使映射后的标识符不再是关键字。

例如,Slice标识符switch被映射到C++的_cpp_switch,以及Java的_switch。

对关键字进行处理的规则可能会产生难以阅读的源码。

像native、throw,或export这样的标识符会与C++或Java(或两者)的关键字发生冲突。

为了让你和别人生活得更轻松一点,你应该避免使用是实现语言的关键字的Slice标识符。

要记住,以后Ice可能会增加除C++和Java以外的语言映射。

尽管期望你总结出所有流行的编程语言的所有关键字并不合理,你至少应该尽量避免使用常用的关键字。

使用像self、import,以及while这样的标识符肯定不是好主意。

转义的标识符:

在关键字的前面加上一个反斜线,你可以把Slice关键字用作标识符,例如:

structdictionary{//错误!

//...

};

struct/dictionary{//OK

//...

};

反斜线会改变关键字通常的含义;在前面的例子中,/dictionary被当作标识符dictionary。

转义机制之所以存在,是要让我们在以后能够在Slice中增加关键字,同时尽量减少对已有规范的影响:

如果某个已经存在的规范碰巧使用了新引入的关键字,你只需在新关键字前加上反斜线,就能够修正该规范。

注意,从风格上说,你应该避免用Slice关键字做标识符(即使反斜线转义允许你这么做)。

保留的标识符:

Slice为Ice实现保留了标识符Ice及以Ice(任何大小写方式)起头的所有标识符。

例如,如果你试图定义一个名为Icecream的类型,Slice编译器会发出错误警告3。

以下面任何一种后缀结尾的Slice标识符也是保留的:

Helper、Holder、Prx,以及Ptr。

Java和C++语言映射使用了这些后缀,保留它们是为了防止在生成的代码中发生冲突。

(注:

ICE1.3的中文手册上没有“模块”这一部分)模块来组织一组相关的语句是为了解决名字冲突。

模块可以包含所有合法的Slice语句和子模块。

你可以用一些不常用的词来给最外层的模块命名,比如公司名、产品名等等。

moduleZeroC{

moduleClient{

//Definitionshere...

};

moduleServer{

//Definitionshere...

};

};

Slice要求所有的定义都是模块的一部分,比如,下面的语句就是非法的。

interfaceI{//错误:

全局空间中只可以有模块

//...

};

多个文件可以共享同一个模块,比如:

moduleZeroC{

//Definitionshere...

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2