MemoryGarden's Blog

努力 -----------大能猫

C++博客 首页 新随笔 联系 聚合 管理
  118 Posts :: 11 Stories :: 20 Comments :: 0 Trackbacks
首先声明我很挫,刚学的。 有很多不会,不明白的地方,虽然是照搬书上的东西,但是自己也写了一些理解,如果您看到错误的话,请您一定要帮我指正。

首先贴个服务端的代码,就是书上的。


 1 #include <Ice/Ice.h>
 2 #include <Printer.h>
 3 using namespace std;
 4 class PrinterI : public Printer {
 5 public:
 6      virtual void printString(const string & s,
 7                               const Ice::Current &);
 8 };
 9 void
10 PrinterI::
11 printString(const string & s, const Ice::Current &)
12 {
13      cout << s << endl;
14 }
15 int
16 main(int argc, char* argv[])
17 {
18      int status = 0;
19      Ice::CommunicatorPtr ic;
20      try {
21          ic = Ice::initialize(argc, argv);
22          Ice::ObjectAdapterPtr adapter
23              = ic->createObjectAdapterWithEndpoints(
24                  "SimplePrinterAdapter""default -p 10000");
25          Ice::ObjectPtr object = new PrinterI;
26          adapter->add(object,
27                       Ice::stringToIdentity("SimplePrinter"));
28          adapter->activate();
29          ic->waitForShutdown();
30      } catch (const Ice::Exception & e) {
31          cerr << e << endl;
32          status = 1;
33      } catch (const char * msg) {
34          cerr << msg << endl;
35          status = 1;
36      }
37      if (ic)
38          ic->destroy();
39      return status;
40 }
41 

   对于一个只打印一个串的服务器而言,这里的代码似乎有很多。不要担
心这一点:大多数代码都是不会变化的公式化代码。对于这个非常简单的
服务器而言,其代码几乎就由这些公式化代码组成。
   每个 Slice 源文件的一开始都有一条用于包括 Ice.h 的指令,在
Ice.h 中包含了 Ice run time 的各种定义。我们还包括了由 Slice 编译器生成
的 Printer.h,其中含有我们的打印机接口的 C++ 定义;为了使以后的
代码保持简洁,我们还导入了 std 名字空间的内容:

1 #include <Ice/Ice.h>
2 #include <Printer.h>
3 using namespace std;
4 


  我们的服务器实现了一个打印机 servant,其类型是 PrinterI。我们查
看 Printer.h 中的生成的代码,发现了以下内容 (为去掉无关细节,进
行了整理)   :

1 class Printer : virtual public Ice::Object {
2 public:
3     virtual void printString(const std::string &,
4                              const Ice::Current & = Ice::Current()
5                             ) = 0;
6 };
7 



这个类是ice对Printer.ice编译后生成的骨架类的部分。

骨架类 :


在服务器端,接口映射到骨架类。对于相应的接口上的每个操作,骨架类都有一个对应的纯虚方法
• 和客户端一样,Slice 模块映射到名字相同的C++ 名字空间,所以骨架类定义会放在名字空间Demo 中。
• 骨架类的名字与Slice 接口的名字(Printer)相同。
• 对于Slice 接口中的每个操作,骨架类都有一个对应的纯虚成员函数。
• 骨架类是抽象基类,因为它的成员函数是纯虚函数。
• 骨架类继承自Ice::Object (这个类形成了Ice 对象层次的根)。


再回到servant上来。
servant :

1 class PrinterI : public Printer {
2 public:
3     virtual void printString(const string & s,
4                              const Ice::Current &);
5 };
6 

printString 方法的实现很简单:它会简单地把它的串参数写到stdout:

1 void
2 PrinterI::
3 printString(const string & s, const Ice::Current &)
4 {
5      cout << s << endl;
6 }
7 
servant 是Ice 对象的物理体现,也就是说,它们是
用具体的编程语言实现的实体,并且在服务器的地址空间中进行实例化。
Servants 为“客户发送的操作调用”提供服务器端行为。
同一个servant 可以向一个或更多对象适配器注册。

按照惯例, servant 类的名字是它们接口的名字加上后缀I,所以Printer
接口的servant 类叫作PrinterI (这只是一个惯例:从Ice run time 的角度来
说,你可以为你的servant 类选用任何你喜欢的名字)。

注意, PrinterI 继承自Demo::PrinerI,也就是说,它派生自它
的骨架类。在定义servant 类时总是使用虚继承是个好主意。严格地说,只
有其实现的接口使用了多继承的servant 才必须使用虚继承;但virtual
关键字并无害处,同时,如果你在开发的中途给接口层次增加多继承, 你
无需回去给你的所有servant 类增加virtual 关键字。
从Ice 的角度来说, PrinterI 类只须实现一个成员函数:继承自骨架的
name 纯虚函数。这使得servant 类成了一个能实例化的具体类。你可以按照
你的实现的需要,增加其他成员函数和数据成员。


接下来是服务器的主程序。注意这段代码的总体结构:

 1 int
 2 main(int argc, char* argv[])
 3 {
 4     int status = 0;
 5     Ice::CommunicatorPtr ic;
 6     try {
 7         // Server implementation here
 8     } catch (const Ice::Exception & e) {
 9         cerr << e << endl;
10         status = 1;
11     } catch (const char * msg) {
12         cerr << msg << endl;
13         status = 1;
14     }
15     if (ic)
16         ic->destroy();
17     return status;
18 }
19 

我们的 try 块的主体含有实际的服务器代码:

 1 ic = Ice::initialize(argc, argv);
 2 Ice::ObjectAdapterPtr adapter
 3     = ic->createObjectAdapterWithEndpoints(
 4         "SimplePrinterAdapter""default -p 10000");
 5 Ice::ObjectPtr object = new PrinterI;
 6 adapter->add(object,
 7              Ice::stringToIdentity("SimplePrinter"));
 8 adapter->activate();
 9 ic->waitForShutdown();
10 

这段代码包含以下步骤:
1. 我们调用 Ice::initialize,初始化 Ice run time (我们之所以把
   argc和argv传给这个调用,是因为服务器可能有run time感兴趣的命令
   行参数;就这个例子而言,服务器不需要任何命令行参数)               。
   initialize 调用返回的是一个智能指针,指向一个 Ice::Communicator 对象,这个指针是 Ice run time 的主句柄。
2. 我们调用 Communicator 实例上的
   createObjectAdapterWithEndpoints,创建一个对象适配器。我
   们传入的参数是 "SimplePrinterAdapter" (适配器的名字)和
   "default -p 10000",后者是要适配器用缺省协议 (TCP/IP)在端
   口 10000 处侦听到来的请求。
3. 这时,服务器端 run time 已经初始化,我们实例化一个 PrinterI 对
   象,为我们的 Printer 接口创建一个 servant。
4. 我们调用适配器的 add,告诉它有了一个新的 servant ;传给 add 的参
   数是我们刚才实例化的 servant,再加上一个标识符。在这里,
   "SimplePrinter" 串是 servant 的名字(如果我们有多个打印机,每个
   打印机都可以有不同的名字,更正确的说法是,都有不同的对象标
   识) 。

5. 接下来,我们调用适配器的 activate 方法激活适配器 (适配器一开
   始是在扣留 (holding)状态创建的;这种做法在下面这样的情况下很
   有用:我们有多个 servant,它们共享同一个适配器,而在所有 servant
   实例化之前我们不想处理请求)     。一旦适配器被激活,服务器就会开始
   处理来自客户的请求。
6. 最后,我们调用 waitForShutdown。这个方法挂起发出调用的线程,
   直到服务器实现终止为止——或者是通过发出一个调用关闭 run time,或者是对某个信号作出响应




假定我们的服务器代码放在一个叫作 Server.cpp 的文件中,我们可以这样编译它:

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

   最后,我们需要把服务器链接成可执行程序:
$ c++ -o server Printer.o Server.o -L$ICE_HOME/lib -lIce -lIceUtil



ps : 因为这个命令被袁飞狠狠的BS了一下。。。原来可以合在一起些。。。 55555 我好菜阿






posted on 2009-12-17 16:29 memorygarden 阅读(1222) 评论(0)  编辑 收藏 引用 所属分类: ICE

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理