【 colorado 】
说明文档位于DPWI第3章,程序位于Ice 3.3.1发布${ICE_HOME}/demo/book/printer。
1、Slice文件
Printer.ice 定义如下:
#ifndef SIMPLE_ICE
#define SIMPLE_ICE
module Demo
{
interface Printer
{
void printString(string s);
};
};
#endif
本Slice文件定义了模块Demo,它含有Printer接口,定义了printString操作,printString 操作接受一个字符串。程序功能是客户端调用printString发送字符串给服务器,服务器将字符串打印出来。
编译本slice文件:
slice2cpp Printer.ice
生成 Printer.h/Printer.cpp 文件,定义了接口的规范,实现了运行时支持的类型以及类型的整编与解编。在我们编写的C/S程序中引用了这些文件,以便使用接口。
2、服务器端
Server.cpp:
//必须包含Ice.h文件,以支持Ice运行时
#include <Ice/Ice.h>
//必须包含Printer.h,以使用Slice规范
#include <Printer.h>
using namespace std;
using namespace Demo;
/*
骨架类Printer根据Printer.ice定义由Slice2cpp编译器生成,
它的printString是纯虚方法,骨架类不能被实例化。
服务者PrinterI类继承自骨架类Printer,提供了printString纯虚方法的实现。
*/
class PrinterI : public Printer {
public:
virtual void printString(const string & s,const Ice::Current &);
};
/*
Ice:Current对象为服务器中操作的实现提供了有关当前执行请求的信息,
如适配器,连接,标识,层面,操作,操作模式,上下文,请求ID等。
*/
void PrinterI::printString(const string & s, const Ice::Current &)
{
cout << s << endl;
}
int
main(int argc, char* argv[])
{
int status = 0;
Ice::CommunicatorPtr ic;
try {
//初始化Ice,获取通讯器,智能指针
ic = Ice::initialize(argc, argv);
//在通讯器ic上创建对象适配器SimplePrinterAdapter,缺省协议(TCP),在端口10000上监听
Ice::ObjectAdapterPtr adapter
= ic->createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -p 10000");
//创建服务者类PrinterI
Ice::ObjectPtr object = new PrinterI;
//将服务者类PrinterI加入对象适配器,服务者类的名称是SimplePrinter,
//客户端必须使用此名称的请求标识来请求服务者的操作。
adapter->add(object,ic->stringToIdentity("SimplePrinter"));
//激活对象适配器,客户端请求现在可以分派给服务者类PrinterI。
adapter->activate();
//挂起当前主函数所在线程,等待通讯器关闭
ic->waitForShutdown();
} catch (const Ice::Exception & e) { //捕捉Ice运行时抛出的异常
cerr << e << endl;
status = 1;
} catch (const char * msg) {//捕捉致命错误,输出错误串
cerr << msg << endl;
status = 1;
}
//通讯器必须初始化过,否则不能调用destroy
if (ic) {
try {
ic->destroy();//销毁通讯器
} catch (const Ice::Exception & e) {
cerr << e << endl;
status = 1;
}
}
return status;
}
3、客户端
#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;
int
main(int argc, char * argv[])
{
int status = 0;
Ice::CommunicatorPtr ic;
try {
//初始化Ice,获取通讯器,智能指针
ic = Ice::initialize(argc, argv);
//创建通讯器的代理基类,该代理使用的请求标识为SimplePrinter,端口号:10000,协议:默认(TCP)
Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:default -p 10000");
//代理基类向下转型为PrinterPrx代理类,调用本操作会向服务器发送请求。
//如果转型成功就返回Printer接口的代理,如果转型失败就返回null代理。
PrinterPrx printer = PrinterPrx::checkedCast(base);
//不是Printer接口的代理,抛出异常
if (!printer)
throw "Invalid proxy";
//是Printer接口的代理,调用代理的操作printString
printer->printString("Hello World!");
} catch (const Ice::Exception & ex) {//捕获Ice运行时异常
cerr << ex << endl;
status = 1;
} catch (const char * msg) {//捕捉致命错误,输出错误串
cerr << msg << endl;
status = 1;
}
//通讯器必须初始化过,否则不能调用destroy
if (ic) {
try {
ic->destroy();//销毁通讯器
} catch (const Ice::Exception & ex) {
cerr << ex << endl;
status = 1;
}
}
return status;
}
4、运行
客户端和服务器使用VC++的工程文件完成编译,然后先运行Server,再运行Client。关闭时,以Ctrl+C结束Server程序。
5、说明
${ICE_HOME}/demo/Ice/minimal是一个与此例非常类似的最小Ice应用程序。不同之处在于minimal的服务器定义了对强制关闭信号的处理,如对Ctrl+C定义了:IceUtil::CtrlCHandler ctrCHandler(onCtrlC);然后实现了static void onCtrlC(int)函数,对接收到Ctrl+C信号进行了处理。另外minimal程序用单独的helloI文件实现了hello接口的sayHello操作规范。
本文所展示的程序比马维达先生中译本(Ice 1.3.0)的程序在异常处理方面有所增强,请读者注意。