客户代码看起来与服务器非常像。下面是完整的代码:
1 #include <Ice/Ice.h>
2 #include <Printer.h>
3 using namespace std;
4 int
5 main(int argc, char * argv[])
6 {
7 int status = 0;
8 Ice::CommunicatorPtr ic;
9 try {
10 ic = Ice::initialize(argc, argv);
11 Ice::ObjectPrx base = ic->stringToProxy(
12 "SimplePrinter:default -p 10000");
13 PrinterPrx printer = PrinterPrx::checkedCast(base);
14 if (!printer)
15 throw "Invalid proxy";
16 printer->printString("Hello World!");
17 } catch (const Ice::Exception & ex) {
18 cerr << ex << endl;
19 status = 1;
20 } catch (const char * msg) {
21 cerr << msg << endl;
22 status = 1;
23 }
24 if (ic)
25 ic->destroy();
26 return status;
27 }
28
注意,总体的代码布局与服务器是一样的:我们包括 Ice run time 的头
和 Slice 编译器生成的头,我们用同样的 try 块和 catch 处理器处理错
误。
try 块中的代码所做的事情是:
1. 和在服务器中一样,我们调用 Ice::initialize 初始化 Ice run
time。
2. 下一步是获取远地打印机的代理。我们调用通信器的 stringToProxy
创建一个代理,所用参数是 "SimplePrinter:default -
p 10000"。注意,这个串包含的是对象标识和服务器所用的端口号
(显然,在应用中硬编码对象标识和端口号,是一种糟糕的做法,但它
目前很有效)。
3. stringToProxy 返回的代理的类型是 Ice::ObjectPrx,这种类型
位于接口和类的继承树的根部。但要实际与我们的打印机交谈,我们需
要的是 Printer 接口、而不是 Object 接口的代理。为此,我们需要调
用 PrinterPrx::checkedCast 进行向下转换。这个方法会发送一
条消息给服务器,实际询问 “这是 Printer 接口的代理吗?”如果是,
这个调用就会返回 Printer 的一个代理;如果代理代表的是其他类型的
接口,这个调用就会返回一个空代理。
4. 我们测试向下转换是否成功,如果不成功,就抛出出错消息,终止客
户。
5. 现在,我们在我们的地址空间里有了一个活的代理,可以调用
printString 方法,把享誉已久的 "Hello World!" 串传给它。服务
器会在它的终端上打印这个串。
客户的编译和链接看起来与服务器很像:
$ c++ -I. -I$ICE_HOME/include -c Printer.cpp Client.cpp
$ c++ -o client Printer.o Client.o -L$ICE_HOME/lib -lIce -lIceUtil