﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-MemoryGarden's Blog-随笔分类-ICE</title><link>http://www.cppblog.com/MemoryGarden/category/12564.html</link><description>努力

                                  -----------大能猫</description><language>zh-cn</language><lastBuildDate>Thu, 17 Dec 2009 13:36:56 GMT</lastBuildDate><pubDate>Thu, 17 Dec 2009 13:36:56 GMT</pubDate><ttl>60</ttl><item><title>Ice --  Hello World 之 客户端</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103417.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 10:20:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103417.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103417.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103417.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103417.html</trackback:ping><description><![CDATA[客户代码看起来与服务器非常像。下面是完整的代码:<br><br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Ice</span><span style="color: #000000;">/</span><span style="color: #000000;">Ice.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Printer.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;std;<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">int</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;Ice::CommunicatorPtr&nbsp;ic;<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ic&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Ice::initialize(argc,&nbsp;argv);<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ice::ObjectPrx&nbsp;</span><span style="color: #0000ff;">base</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">stringToProxy(<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">SimplePrinter:default&nbsp;-p&nbsp;10000</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrinterPrx&nbsp;printer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;PrinterPrx::checkedCast(</span><span style="color: #0000ff;">base</span><span style="color: #000000;">);<br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">printer)<br></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">Invalid&nbsp;proxy</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printer</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">printString(</span><span style="color: #000000;">"</span><span style="color: #000000;">Hello&nbsp;World!</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Exception&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;ex)&nbsp;{<br></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cerr&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;ex&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;msg)&nbsp;{<br></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cerr&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;msg&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br></span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;}<br></span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(ic)<br></span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">destroy();<br></span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;status;<br></span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;"></span></div>
<br><br>&nbsp;&nbsp; 注意,总体的代码布局与服务器是一样的:我们包括 Ice run time 的头<br>和 Slice 编译器生成的头,我们用同样的 try 块和 catch 处理器处理错<br>误。<br>&nbsp;&nbsp; try 块中的代码所做的事情是:<br>1. 和在服务器中一样,我们调用 Ice::initialize 初始化 Ice run<br>&nbsp;&nbsp; time。<br><br>2. 下一步是获取远地打印机的代理。我们调用通信器的 stringToProxy<br>&nbsp;&nbsp; 创建一个代理,所用参数是 "SimplePrinter:default -<br>&nbsp;&nbsp; p 10000"。注意,这个串包含的是对象标识和服务器所用的端口号<br>&nbsp; (显然,在应用中硬编码对象标识和端口号,是一种糟糕的做法,但它<br>&nbsp;&nbsp; 目前很有效)。<br><br>3. stringToProxy 返回的代理的类型是 Ice::ObjectPrx,这种类型<br>&nbsp;&nbsp; 位于接口和类的继承树的根部。但要实际与我们的打印机交谈,我们需<br>&nbsp;&nbsp; 要的是 Printer 接口、而不是 Object 接口的代理。为此,我们需要调<br>&nbsp;&nbsp; 用 PrinterPrx::checkedCast 进行向下转换。这个方法会发送一<br>&nbsp;&nbsp; 条消息给服务器,实际询问 &#8220;这是 Printer 接口的代理吗?&#8221;如果是,<br>&nbsp;&nbsp; 这个调用就会返回 Printer 的一个代理;如果代理代表的是其他类型的<br>&nbsp;&nbsp; 接口,这个调用就会返回一个空代理。<br><br><br>4. 我们测试向下转换是否成功,如果不成功,就抛出出错消息,终止客<br>&nbsp;&nbsp; 户。<br><br><br>&nbsp;5. 现在,我们在我们的地址空间里有了一个活的代理,可以调用<br>&nbsp;&nbsp;&nbsp; printString 方法,把享誉已久的 "Hello World!" 串传给它。服务<br>&nbsp;&nbsp;&nbsp; 器会在它的终端上打印这个串。<br><br><br><br>&nbsp;&nbsp;&nbsp; 客户的编译和链接看起来与服务器很像:<br>$ c++ -I. -I$ICE_HOME/include -c Printer.cpp Client.cpp<br>$ c++ -o client Printer.o Client.o -L$ICE_HOME/lib -lIce -lIceUtil<br><br><br><br><br><br><br><br><br><br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 18:20 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice --  Hello World 之 服务端</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103406.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 08:29:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103406.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103406.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103406.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103406.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103406.html</trackback:ping><description><![CDATA[首先声明我很挫，刚学的。 有很多不会，不明白的地方，虽然是照搬书上的东西，但是自己也写了一些理解，如果您看到错误的话，请您一定要帮我指正。<br><br>首先贴个服务端的代码，就是书上的。<br><br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Ice</span><span style="color: #000000;">/</span><span style="color: #000000;">Ice.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Printer.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;std;<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PrinterI&nbsp;:&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Printer&nbsp;{<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;printString(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;s,<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Current&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">);<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">};<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">void</span><span style="color: #000000;"><br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">PrinterI::<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">printString(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;s,&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Current&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">)<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;s&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">int</span><span style="color: #000000;"><br></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ice::CommunicatorPtr&nbsp;ic;<br></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ic&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Ice::initialize(argc,&nbsp;argv);<br></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ice::ObjectAdapterPtr&nbsp;adapter<br></span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">createObjectAdapterWithEndpoints(<br></span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">SimplePrinterAdapter</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">default&nbsp;-p&nbsp;10000</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ice::ObjectPtr&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PrinterI;<br></span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adapter</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">add(</span><span style="color: #0000ff;">object</span><span style="color: #000000;">,<br></span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ice::stringToIdentity(</span><span style="color: #000000;">"</span><span style="color: #000000;">SimplePrinter</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br></span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;adapter</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">activate();<br></span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">waitForShutdown();<br></span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Exception&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;e)&nbsp;{<br></span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cerr&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;e&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br></span><span style="color: #008080;">33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;msg)&nbsp;{<br></span><span style="color: #008080;">34</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cerr&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;msg&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br></span><span style="color: #008080;">36</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080;">37</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(ic)<br></span><span style="color: #008080;">38</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">destroy();<br></span><span style="color: #008080;">39</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;status;<br></span><span style="color: #008080;">40</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">41</span>&nbsp;<span style="color: #000000;"></span></div>
<br>&nbsp;&nbsp; 对于一个只打印一个串的服务器而言,这里的代码似乎有很多。不要担<br>心这一点:大多数代码都是不会变化的公式化代码。对于这个非常简单的<br>服务器而言,其代码几乎就由这些公式化代码组成。<br>&nbsp;&nbsp; 每个 Slice 源文件的一开始都有一条用于包括 Ice.h 的指令,在<br>Ice.h 中包含了 Ice run time 的各种定义。我们还包括了由 Slice 编译器生成<br>的 Printer.h,其中含有我们的打印机接口的 C++ 定义;为了使以后的<br>代码保持简洁,我们还导入了 std 名字空间的内容:<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Ice</span><span style="color: #000000;">/</span><span style="color: #000000;">Ice.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Printer.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;std;<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;"></span></div>
<br><br>&nbsp; 我们的服务器实现了一个打印机 servant,其类型是 PrinterI。我们查<br>看 Printer.h 中的生成的代码,发现了以下内容 (为去掉无关细节,进<br>行了整理)&nbsp;&nbsp; :<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Printer&nbsp;:&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Ice::Object&nbsp;{<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;printString(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;std::</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">,<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Current&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Ice::Current()<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">};<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;"></span></div>
<br><br><br>这个类是ice对Printer.ice编译后生成的骨架类的部分。<br><br>骨架类 ： <br><br><br>在服务器端，接口映射到骨架类。对于相应的接口上的每个操作，骨架类都有一个对应的纯虚方法<br>&#8226; 和客户端一样，Slice 模块映射到名字相同的C++ 名字空间，所以骨架类定义会放在名字空间Demo 中。<br>&#8226; 骨架类的名字与Slice 接口的名字（Printer）相同。<br>&#8226; 对于Slice 接口中的每个操作，骨架类都有一个对应的纯虚成员函数。<br>&#8226; 骨架类是抽象基类，因为它的成员函数是纯虚函数。<br>&#8226; 骨架类继承自Ice::Object （这个类形成了Ice 对象层次的根）。<br><br><br>再回到servant上来。<br>servant ：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PrinterI&nbsp;:&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Printer&nbsp;{<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;printString(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;s,<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Current&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">);<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">};<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;"></span></div>
<br>printString 方法的实现很简单:它会简单地把它的串参数写到stdout:<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">void</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">PrinterI::<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">printString(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;s,&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Current&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">)<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;s&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;"></span></div>
servant 是Ice 对象的物理体现，也就是说，它们是<br>用具体的编程语言实现的实体，并且在服务器的地址空间中进行实例化。<br>Servants 为&#8220;客户发送的操作调用&#8221;提供服务器端行为。<br>同一个servant 可以向一个或更多对象适配器注册。<br><br>按照惯例， servant 类的名字是它们接口的名字加上后缀I，所以Printer<br>接口的servant 类叫作PrinterI （这只是一个惯例：从Ice run time 的角度来<br>说，你可以为你的servant 类选用任何你喜欢的名字）。<br><br>注意， PrinterI 继承自Demo::PrinerI，也就是说，它派生自它<br>的骨架类。在定义servant 类时总是使用虚继承是个好主意。严格地说，只<br>有其实现的接口使用了多继承的servant 才必须使用虚继承；但virtual<br>关键字并无害处，同时，如果你在开发的中途给接口层次增加多继承， 你<br>无需回去给你的所有servant 类增加virtual 关键字。<br>从Ice 的角度来说， PrinterI 类只须实现一个成员函数：继承自骨架的<br>name 纯虚函数。这使得servant 类成了一个能实例化的具体类。你可以按照<br>你的实现的需要，增加其他成员函数和数据成员。<br><br><br>接下来是服务器的主程序。注意这段代码的总体结构:<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">int</span><span style="color: #000000;"><br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Ice::CommunicatorPtr&nbsp;ic;<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Server&nbsp;implementation&nbsp;here<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Exception&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;e)&nbsp;{<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cerr&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;e&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;msg)&nbsp;{<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cerr&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;msg&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;endl;<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(ic)<br></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">destroy();<br></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;status;<br></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;"></span></div>
<br>我们的 try 块的主体含有实际的服务器代码:<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">ic&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Ice::initialize(argc,&nbsp;argv);<br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">Ice::ObjectAdapterPtr&nbsp;adapter<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">createObjectAdapterWithEndpoints(<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">SimplePrinterAdapter</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">default&nbsp;-p&nbsp;10000</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">Ice::ObjectPtr&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PrinterI;<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">adapter</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">add(</span><span style="color: #0000ff;">object</span><span style="color: #000000;">,<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ice::stringToIdentity(</span><span style="color: #000000;">"</span><span style="color: #000000;">SimplePrinter</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">adapter</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">activate();<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">ic</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">waitForShutdown();<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;"></span></div>
<br>这段代码包含以下步骤:<br>1. 我们调用 Ice::initialize,初始化 Ice run time (我们之所以把<br>&nbsp;&nbsp; argc和argv传给这个调用,是因为服务器可能有run time感兴趣的命令<br>&nbsp;&nbsp; 行参数;就这个例子而言,服务器不需要任何命令行参数)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 。<br>&nbsp;&nbsp; initialize 调用返回的是一个智能指针,指向一个 Ice::Communicator 对象,这个指针是 Ice run time 的主句柄。<br>2. 我们调用 Communicator 实例上的<br>&nbsp;&nbsp; createObjectAdapterWithEndpoints,创建一个对象适配器。我<br>&nbsp;&nbsp; 们传入的参数是 "SimplePrinterAdapter" (适配器的名字)和<br>&nbsp;&nbsp; "default -p 10000",后者是要适配器用缺省协议 (TCP/IP)在端<br>&nbsp;&nbsp; 口 10000 处侦听到来的请求。<br>3. 这时,服务器端 run time 已经初始化,我们实例化一个 PrinterI 对<br>&nbsp;&nbsp; 象,为我们的 Printer 接口创建一个 servant。<br>4. 我们调用适配器的 add,告诉它有了一个新的 servant ;传给 add 的参<br>&nbsp;&nbsp; 数是我们刚才实例化的 servant,再加上一个标识符。在这里,<br>&nbsp;&nbsp; "SimplePrinter" 串是 servant 的名字(如果我们有多个打印机,每个<br>&nbsp;&nbsp; 打印机都可以有不同的名字,更正确的说法是,都有不同的对象标<br>&nbsp;&nbsp; 识) 。<br><br>5. 接下来,我们调用适配器的 activate 方法激活适配器 (适配器一开<br>&nbsp;&nbsp; 始是在扣留 (holding)状态创建的;这种做法在下面这样的情况下很<br>&nbsp;&nbsp; 有用:我们有多个 servant,它们共享同一个适配器,而在所有 servant<br>&nbsp;&nbsp; 实例化之前我们不想处理请求)&nbsp;&nbsp;&nbsp;&nbsp; 。一旦适配器被激活,服务器就会开始<br>&nbsp;&nbsp; 处理来自客户的请求。<br>6. 最后,我们调用 waitForShutdown。这个方法挂起发出调用的线程,<br>&nbsp;&nbsp; 直到服务器实现终止为止——或者是通过发出一个调用关闭 run time,或者是对某个信号作出响应<br><br><br><br><br>假定我们的服务器代码放在一个叫作 Server.cpp 的文件中,我们可以这样编译它:<br><br>$ c++ -I. -I$ICE_HOME/include -c Printer.cpp Server.cpp<br><br>&nbsp;&nbsp; 最后,我们需要把服务器链接成可执行程序:<br>$ c++ -o server Printer.o Server.o -L$ICE_HOME/lib -lIce -lIceUtil<br><br><br><br>ps ： 因为这个命令被袁飞狠狠的BS了一下。。。原来可以合在一起些。。。 55555 我好菜阿<br><br><br><br><br><br><br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103406.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 16:29 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103406.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice run time -- 对象标识</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103404.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 08:21:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103404.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103404.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103404.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103404.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103404.html</trackback:ping><description><![CDATA[<br><br>每个Ice 对象都有一个对象标识，其定义如下所示：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">module&nbsp;Ice&nbsp;{<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;Identity&nbsp;{<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name;<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;category;<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;};<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">};</span></div>
<br>你可以看到，对象标识由一对串组成：name 和category。name 或category<br>都可以是空串（如果某个代理包含的标识的name 和category 都是空<br>的， Ice 就把这个代理解释成null 代理）。完整的对象标识由name 和<br>category 组合而成，也就是说，两个标识要相等，它们的name 和category<br>都必须相同。category 成员通常是空串，除非你在使用servant 定位器<br><br><br><br><br>这个对象标识应该就是ASM 里面的键&nbsp; 当然，值就是代理了（也就是指针，也就是在内存中的位置）。。。（不敢多说了。。。砖头阿。。。）<br><br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;Ice&nbsp;{<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">std::</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;identityToString(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Identity&nbsp;id);<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">Ice::Identity&nbsp;stringToIdentity(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;std::</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;s);<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">};</span></div>
<br>这里的 stringToIdentity(const std::string&amp; s)&nbsp; 这个方法很雷的只传入了一个参数，这样的话是不是category 成员就直接&#8220;&#8221;了。。。实在是太不受重视了。。。不过我看的只是少部分。。乎略我。。。<br><br> <img src ="http://www.cppblog.com/MemoryGarden/aggbug/103404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 16:21 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice run time -- 对象适配器</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103403.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 08:13:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103403.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103403.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103403.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103403.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103403.html</trackback:ping><description><![CDATA[<br>好多不懂的。。。mlgbd<br><br>对象适配器<br><br><br><br>一个通信器含有一个或更多对象适配器。对象适配器处在Ice run time<br>和服务器之间的界线上，负有这样一些责任：一个通信器含有一个或更多对象适配器。对象适配器处在Ice run time<br>和服务器之间的界线上，负有这样一些责任：<br>&#8226; 它把Ice对象映射到到来请求的servant，并把请求分派给每个servant中的<br>应用代码（也就是说，对象适配器实现了一个向上调用接口，把Ice<br>run time 与服务器中的应用代码连接在一起）。<br>&#8226; 它协助进行生命周期操作，使得Ice对象和servant在创建和销毁时不会出<br>现竞争状况。<br>&#8226; 它提供一个或更多传输端点。客户通过这些端点访问适配器所提供的Ice<br>对象（创建没有端点的对象适配器也是可能的。这样的适配器被用于<br>双向回调——参见第24 章）。<br>每个对象适配器都有一个或更多servant，对Ice 对象进行体现；同时还<br>有一个或更多传输端点。如果对象适配器拥有的传输端点不止一个，所有<br>向该适配器作了注册的servant 可以在任何一个端点上响应到来的请求。换<br>句话说，如果对象适配器有多个传输端点，这些端点代表的是通往同一组<br>对象的不同通信路径（例如，通过不同的传输机制）。<br>每个对象适配器都只属于一个通信器（但一个通信器可以有多个对象<br>适配器）。<br>每个对象适配器可以非强制性地拥有自己的线程池，你可以通过<br>&lt;adapter-name&gt;.ThreadPool.Size 属性来使用这个特性（参见附录<br>C）。如果使用了这个特性，在分派针对该适配器的客户调用时，使用的是<br>适配器的线程池中的线程，而不会使用通信器的服务器线程池中的线程。<br><br><br>活动Servant 映射表 ： <br><br><br>每个对象适配器都维护有一个叫作活动servant 映射表（active servant<br>map）的数据结构。 活动servant 映射表（简称为ASM）是一个查找表，用<br>于把对象标识映射到servant：在C++ 里，查找值是智能指针，指向对应的<br>servant 在内存中的位置；<br><span style="color: red;">当客户把操作调用发给服务器时，请求的目标是特定的传输端点。传输端</span><br style="color: red;"><span style="color: red;">点隐含地标识了请求所针对的对象适配器（因为同一个端点只能绑定到一</span><br style="color: red;"><span style="color: red;">个对象适配器）</span><br>客户藉以发送请求的代理含有对应的对象的标识，客户<br>端run time 会在线路上随调用一起发送这个对象标识。对象适配器继而使<br>用这个对象标识、在它的ASM 中查找正确的servant，把调用分派给它<br>经由代理、把请求关联到正确的servant 的过程叫作绑定。图16.1 的例<br>子所描述的是直接绑定 ：传输端点是嵌在代理中的<br>如果在适配器的ASM 中，客户请求所包含的对象标识没有对应的条<br>目，适配器就会把ObjectNotExistException 返回给客户<br><br><br>对象适配器接口 ： <br>对象适配器是本地接口<br><br>module Ice {<br>&nbsp;&nbsp;&nbsp; local interface ObjectAdapter {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; string getName();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Communicator getCommunicator();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object* add(Object servant, Identity id);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object* addWithUUID(Object servant);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void remove(Identity id);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void activate();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void hold();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void waitForHold();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void deactivate();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void waitForDeactivate();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // ...<br>&nbsp;&nbsp;&nbsp; };<br>};<br><br>&#8226; getName 操作返回适配器的名字，这个名字是在调用Communicator::createObjectAdapter 或Communicator::createObjectAdapter-WithEndpoints 时传入的。<br>&#8226; getCommunicator 操作返回先前用于创建该适配器的通信器。注意，在ObjectAdapter 接口中还有其他操作；我们将在本章余下的各个部分讨论这些操作。<br><br>对象适配器提供了一些操作，用于管理servant 激活和解除激活：<br><br>Servant 激活与解除激活<br><br>术语servant 激活指的是，向Ice run time 告知某个Ice 对象的servant 的<br>存在。如果你激活一个servant，在图16.1 所示的活动servant 映射表中就会<br>增加一个条目。看待servant 激活的另一种方式是，把它看成是在&#8220;Ice 对<br>象的标识&#8221;与&#8220;对应的用编程语言编写的、负责为该Ice 对象处理请求的<br>servant&#8221;之间创建链接。一旦Ice run time 知道了这个链接，它就可以把到<br>来的请求分派给正确的servant。如果没有这样的链接，也就是说，在ASM<br>中没有对应的条目，针对该标识的到来请求就会引发<br>ObjectNotExistException。一旦servant 被激活，我们就认为它体现了对应<br>的Ice 对象。<br>与之相反的操作叫作servant 解除激活。如果你解除某个servant 的激<br>活，就会从ASM 中移除针对特定标识的一个条目。 自此以后，针对该标识<br>的到来请求就不会再分派给servant，并且会引发<br>ObjectNotExistException。<br><br>这些操作的行为是：<br>&#8226; add&nbsp; add 操作把一个具有指定标识的servant 增加到ASM中。一旦add 被调用，请求就会分派给这个servant。返回值是这个servant 所体现的Ice对象的代理。这个代理嵌有传给add 的标识。<br>注意，通过不同的标识多次激活同一个servant，这是可能的。在这<br>种情况下，同一个servant 将体现多个Ice 对象。我们将在16.7.2 节更详<br>细地探索这个特性的影响。<br><br>&#8226; addWithUUID&nbsp; addWithUUID 操作的行为和add 操作一样，但你不需要为servant 提供标识。addWithUUID 会生成一个UUID （参见[14]），作为对应的Ice 对<br>象的标识。你可以调用返回的代理的ice_getIdentity 操作，取得生成的标识。addWithUUID 可用于创建临时对象的标识，比如短期存在的对象<br><br>&#8226; remove&nbsp; remove 操作中断标识与其servant 之间的关联，从ASM 中移除对应的条目。一旦servant 解除了激活，新到来的针对已移除标识的请求会引<br>发ObjectNotExistException。当remove 被调用时，正在servant 中执行的请求可以正常完成。一旦servant 的最后一个请求完成，对象适配器就会丢弃它的智能指针这时，如果你不再持有指向这个servant 的引用或智能指针，它就可以被销毁实际效果就是，一旦解除了激活的servant 空闲下来，它就会被销毁。如果你解除对象适配器的激活，将会隐含地调用它的活动servants 的remove 操作<br><br><br>对象适配器具有以下处理状态（processing state）：<br><br>适配器状态<br>&#8226; 扣留状态（holding）<br>在这种状态下，适配器的任何到来的请求都会被&#8220;扣留&#8221;，也就是<br>说，不会被分派给servant。<br>在使用TCP/IP （及其他面向流的协议）当被调用时，如果适配器处<br>在扣留状态，服务器端run time 就会停止从对应的传输端点读取数据。<br>此外，它也不接受客户发送的连接请求。这意味着，如果客户向处在扣<br>留状态的适配器发送请求，客户最终会收到TimeoutException 或<br>ConnectTimeoutException （除非在定时器超时之前，适配器变成了活<br>动状态）。<br>在使用UDP 时，如果客户请求到达处在扣留状态的适配器，请求将<br>被丢弃。<br>刚创建的适配器都处在扣留状态。这意味着，在你让适配器变成活<br>动状态之前，请求不会被分派。<br><br>&#8226; 活动状态<br>在这种状态下，适配器会接受到来的请求，把它们分派给servant。<br>新创建的适配器一开始处在扣留状态。只要你让适配器变成活动状态，<br>它就会开始分派请求。<br>你可以随意在活动和扣留状态之间转换。<br><br>&#8226; 不活动<br>在这种状态下，适配器在概念上已经被销毁（或处在销毁过程<br>中）。解除适配器的激活会销毁与该适配器相关联的所有传输端点。当<br>适配器变成不活动状态时，仍在执行的请求可以完成，但适配器不会再<br>接受新的请求（发出新请求的客户会收到异常）。一旦适配器解除了激<br>活，你不能再在同一进程中重新激活它。<br>ObjectAdapter 接口提供了一些操作，允许你改变适配器状态，或者等<br>待状态改变完成：<br><br>&#8226; activate<br>activate 操作让适配器变成活动状态。激活已经处在活动状态的适<br>配器没有任何效果。一旦activate 被调用， Ice run time 就会开始把请<br>求分派给适配器的servants。<br><br>&#8226; hold<br>hold 操作让适配器变成扣留状态。在调用hold 之后到达的请求都会<br>像第373 页所说的那样被扣留。在hold 被调用时正在执行的请求可以<br>正常完成。注意， hold 会立即返回，不会等待正在执行的请求完成。<br><br>&#8226; waitForHold<br>waitForHold 操作挂起发出调用的线程，直到适配器迁移到扣留状态<br>为止，也就是说，直到正在执行的所有请求完成为止。你可以从多个线<br>程调用waitForHold，也可以在适配器处在活动状态时调用<br>waitForHold。如果适配器处在不活动状态，对它调用waitForHold 不会<br>做任何事情，并且会立即返回。<br><br><br>&#8226; deactivate 操作让适配器变成不活动状态。在调用deactivate 之后<br>到达的请求会被拒绝，但正在执行的请求可以完成。一旦适配器处在不<br>活动状态，它不能再被重新激活。如果适配器处在不活动状态，对它调<br>用activate、hold、waitForHold，或deactivate 没有任何效果。一<br>旦变得空闲，与该适配器相关联的任何servants 都会被销毁。注意，<br>deactivate 会立即返回，不会等待正在执行的请求完成。<br><br>&#8226; waitForDeactivate<br>waitForDeactivate 操作挂起发出调用的线程，直到适配器迁移到不<br>活动状态为止，也就是说，直到所有正在执行的线程完成、所有的传输<br>端点关闭、所有相关联的servants 销毁为止。你可以从多个线程调用<br>waitForDeactivate，也可以在适配器处在活动或扣留状态时调用<br>waitForDeactivate。如果适配器处在不活动状态，对它调用wait-<br>ForDeactivate 不会做任何事情，并且会立即返回。<br><br><br><br><br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 16:13 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice run time -- 通信器</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103401.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 07:39:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103401.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103401.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103401.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103401.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103401.html</trackback:ping><description><![CDATA[只贴出一些自己懂的。 以后懂多少贴多少<br><br><br>通信器的接口是用Slice 定义的。下面是其部分接口：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">module&nbsp;Ice&nbsp;{<br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;Communicator&nbsp;{<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;proxyToString(Object</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;obj);<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;stringToProxy(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;str);<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectAdapter&nbsp;createObjectAdapter(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name);<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectAdapter&nbsp;createObjectAdapterWithEndpoints(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name,</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;endpoints);<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;shutdown();<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;waitForShutdown();<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;destroy();<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;};<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">};</span></div>
<br><br>通信器提供了一些操作：<br>&#8226; proxyToString<br>&#8226; stringToProxy<br>这两个操作允许你把代理转换成串化表示，或进行反向转换。<br>&#8226; createObjectAdapter<br>&#8226; createObjectAdapterWithEndpoints<br>这两个操作创建新的对象适配器。每个对象适配器都与一个或更多<br>传输端点关联在一起。一个对象适配器通常拥有一个传输端点。但是，<br>一个对象适配器也可以提供多个传输端点。如果是这样，这些端点可以<br>通往同一组对象，但代表访问这些对象的不同手段。这很有用，例如，<br>服务器在防火墙后面，但必须让内部和外部的客户都能访问它；把适配<br>器同时绑定到内部和外部接口，就可以其中任何一个接口访问在服务器<br>中实现的对象了。<br>createObjectAdapter 根据配置信息（参见第20 章）来确定把自己<br>绑定到哪个端点，而createObjectAdapterWithEndpoints 允许你为新<br>适配器指定传输端点。你通常会优先于createObjectAdapterWithEndpoints<br>使用createObjectAdapter。这样，就能把与传输机制相关的信<br>息（比如主机名和端口号）放在 源码外面，通过改变属性，你可以对<br>应用进行重配置（于是，在传输端点需要改变时，不用重新进行编<br>译）。<br>&#8226; shutdown<br>这个操作关闭服务器端的Ice run time：<br>&#8226; 在shutdown 被调用时，仍处在执行过程中的操作调用可以正常完成。<br>shutdown 不会等待这些操作完成；在shutdown 返回时，你所知道的<br>是：不会再有新的请求被分派，但在你调用shutdown 时已经在执行<br>之中的操作可能仍在运行。你可以调用waitForShutdown，等待仍在<br>执行的操作完成。<br>&#8226; 在服务器调用shutdown 之后到达的操作调用或者会失败（抛出<br>ConnectFailedException），或者会被透明地重定向到服务器的某个<br>新实例（参见第20 章）。<br>&#8226; waitForShutdown<br>这个操作挂起发出调用的线程，直到通信器关闭为止（也就是说，<br>直到在服务器中不再有操作在执行为止）。这样，你可以在销毁通信器<br>之前，等待服务器空闲下来。<br>&#8226; destroy<br>这个操作销毁通信器及其相关资源，比如线程、通信端点，以及内<br>存资源。一旦你销毁了通信器（因此也就销毁了该通信器的run<br>time），你不能再调用其他任何Ice 操作（除了创建另外的通信器）。<br>在离开程序的main 函数之前要调用destroy，这是强制性的。不这<br>样做会导致不确定的行为。<br>在离开main 之前调用destroy 是必需的，因为destroy 会在返回<br>之前等待所有运行中的线程终止。如果你没有调用destroy 就离开<br>main，你就会留下许多仍在运行的线程；许多线程包不允许你这样做，<br>你最终会使程序崩溃。<br>如果你没有调用shutdown 就调用destroy，在这个调用返回之前，它会<br>等待所有执行中的操作调用完成（也就是说， destroy 的实现隐含地调用<br>shutdown，然后调用waitForShutdown）。shutdown （因此，也包括<br>destroy）会解除与通信器相关联的所有对象适配器的激活。<br>在客户端，如果你在操作执行过程中调用shutdown，这些操作会终止，<br>抛出CommunicatorDestroyedException。<br><br><br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103401.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 15:39 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103401.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice --  Hello World 之 Slice 定义</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103400.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 06:58:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103400.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103400.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103400.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103400.html</trackback:ping><description><![CDATA[Slice1 （Specification Language for Ice）是一种用于使对象接口与其实现<br>相分离的基础性抽象机制。 Slice 在客户与服务器之间建立合约，描述应用<br>所使用的各种类型及对象接口。这种描述与实现语言无关，所以编写客户<br>所用的语言是否与编写服务器所用的语言相同，这没有什么关系。<br>Slice 定义由编译器编译到特定的实现语言 。编译器把与语言无关的定<br>义翻译成针对特定语言的类型定义和API。开发者使用这些类型和API 来<br>提供应用功能，并与Ice 交互。用于各种实现语言的翻译算法称为语言映射<br>（language mappings）。Ice 目前定义了C++ 和Java 的语言映射。<br>因为Slice 描述的是接口和类型（不是实现），它是一种纯粹的描述性<br>语言；你无法用Slice 编写可执行语句。<br>Slice 定义关注的焦点是对象接口、这些接口所支持的操作，以及操作<br>可能引发的异常。此外， Slice 还提供了一些用于对象持久的特性（参见第<br>21 章）。这需要相当多的支持机制；特别地， Slice 的相当一部分关注的是<br>数据类型的定义。这是因为，只有在其类型用Slice 进行了定义之后，数据<br>才能在客户与服务器之间交换。你不能在客户与服务器之间交换任意的<br>C++ 数据，因为 这可能会摧毁Ice 的语言无关性。但是，你总能创建一种<br>Slice 类型定义，与你想要发送的C++ 数据相对应，然后你就可以传送这种<br>Slice 类型了。<br>在此我们将介绍Slice 的完整语法和语义。因为Slice 的许多语法和语义<br>都是以C++ 和Java 为基础的，我们将特别关注Slice 与C++ 或Java 不同的<br>部分，或是Slice 以某种方式限制了等价的C++ 或Java 特性的部分。与<br>C++ 和Java 特性相同的Slice 特性通常会用例子来说明。<br><br>文件命名&nbsp;&nbsp; <br>含有Slice 定义的文件必须以.ice 扩展名结尾，例如， Clock.ice<br>就是一个有效的文件名。编译器拒绝接受其他扩展名。<br><br><br><br>预处理<br><br>Slice 支持#ifndef、#define、#endif，以及#include 预处理指令。它<br>们的使用方式有严格的限制：<br>&#8226; 你只能把#ifndef、#define，以及#endif 指令用于创建双包括<br>（double-include）块<br>&#8226; #include 指令只能出现在Slice 源文件的开头，也就是说，它们必须出现<br>在其他所有Slice 定义的前面。此外，在使用#include 指令时，只允许<br>使用&lt;&gt; 语法来指定文件名，不能使用""。<br><br><br><br>关键字 ： <br><br>以下标识符是Slice 关键字：<br>关键字的大小写必须按照给出的方式拼写。<br>bool &nbsp; enum&nbsp;&nbsp; implements &nbsp; module &nbsp; string<br>byte &nbsp; exception&nbsp;&nbsp; int&nbsp;&nbsp; nonmutating&nbsp;&nbsp; struct<br>class &nbsp; extends&nbsp;&nbsp; interface &nbsp; Object &nbsp; throws<br>const&nbsp;&nbsp; false &nbsp; local out &nbsp; true<br>dictionary &nbsp; float &nbsp; LocalObject &nbsp; sequence void<br>double&nbsp;&nbsp; idempotent &nbsp; long &nbsp; short<br><br><br>结构 ：<br><br>Slice 支持含有一个或多个有名称的成员的结构，这些成员可以具有任<br>意类型，包括用户定义的复杂类型。例如：<br>struct TimeOfDay {<br>short hour; // 0 - 23<br>short minute; // 0 - 59<br>short second; // 0 - 59<br>};<br>与在 C++ 里一样，这个定义引入了一种叫作TimeOfDay 的新类型。结构<br>定义会形成名字空间，所以结构成员的名字只需在围绕它们的结构里是唯<br>一的。<br>在结构内部，只能出现数据成员定义，这些定义必须使用有名字的类<br>型。例如，你不可能在结构内定义结构：<br><br><br>这个规则大体上适用于Slice：类型定义不能嵌套（除了模块确实支持<br>嵌套——参见4.11 节）。其原因是，对于某些目标语言而言，嵌套的类型<br>定义可能会难以实现，而且，即使能够实现，也会极大地使作用域解析规<br>则复杂化。对于像Slice 这样的规范语言而言，嵌套的类型定义并无必要<br>——你总能以下面的方式编写上面的定义（这种方式在风格上也更加整<br>洁）：<br>struct Point {<br>short x;<br>short y;<br>};<br>struct TwoPoints { // Legal (and cleaner!)<br>Point coord1;<br>Point coord2;<br>};<br><br>代理 ：<br>代理就像是能代表对象的指针（个人认为）。代理的语义与C++ 类实例指针的语义非常像：<br><br>&#8226; 代理可以为null （参见第88 页）。<br>&#8226; 代理可以悬空（dangle）（指向的对象已经不存在）<br>&#8226; 代理充当的是远地对象的本地&#8220;大使&#8221;；如果你调<br>用代理上的某个操作，你的调用会转发给实际的对象实现。如果对象实现<br>是在另外的地址空间中，就会产生一个远地过程调用；如果对象实现是并<br>置在相同的地址空间中的， Ice 就会使用普通的本地函数调用，从代理那里<br>调用对象实现<br>代理不能访问数据成员。这是因为代理没有数据成员的概念，它们代表的是接口，通过代理只能访问它的操作。<br><br>Slice 有很多东西，&nbsp; 就写了一些能看懂，或者个人感觉常用的。 <br><br>我们针对Hello World 来编写它的Slice 它就是要客户端给告诉服务端执行一个在服务端输出一句话。<br><br>所以这个Printer.ice 文件的编写非常简单<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">module&nbsp;Demo{<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;Printer{<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;printString(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;s);<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;};<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">};<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;"></span></div>
<br>编译 ：&nbsp; slice2cpp Printer.ice<br><br>编译后生成Printer.h&nbsp; 和 Printer.cpp 两个文件。 这两个文件要被客户端以及服务端用到 内部封装了我们定义的Printer这个接口，对于c++来说，也就是一个有着 类似virtual void printString(string s) = 0&nbsp; 这样的一个纯虚函数的一个骨架类，用来服务器端我们来继承并搞一个servant&nbsp; 。&nbsp; 同样 ，对于客户端， 有一个PrinterPrx它是一个类似c++指针的东西，反正很像的，我们可以通过它，和ice帮助我们封装好的一些通讯的方法，以及它的一些别的方法来编写我们的逻辑代码，就像编写在客户端一样，很方便。<br><br><br><br><br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 14:58 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice 在架构上提供的好处</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103393.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 05:38:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103393.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103393.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103393.html</trackback:ping><description><![CDATA[Ice 在架构上为应用开发者提供了一些好处：<br>&#8226; 面向对象的语义<br>Ice &#8220;在线路上&#8221;完全保留了 面向对象范型。所有的操作调用都使用<br>迟后绑定，所以操作的实现的选定，是根据对象在运行时的（而不是<br>静态的）实际类型决定的。<br>&#8226; 支持同步和异步的消息传递<br>Ice 提供了同步和异步的操作调用和分派，并且通过IceStorm 提供了<br>发布－订阅消息传递机制。这样，你可以根据你的应用的需要来选择通<br>信模型，而不必把你的应用硬塞进某种模型里。<br>&#8226; 支持多个接口<br>通过facets，对象可以提供多个不相关的接口，同时又跨越这些接<br>口、保持单一的对象标识。这提供了极大的灵活性，特别是在这样的情<br>况下：应用在发生演化，但又需要与更老的、已经部署的客户保持兼<br>容。<br>&#8226; 机器无关性<br>客户及服务器与底层的机器架构屏蔽开来。对于应用代码而言，像<br>字节序和填充这样的问题都隐藏了起来。<br>&#8226; 语言无关性<br>客户和服务器可以分别部署，所用语言也可以不同（目前支持<br>C++、Java，以及PHP （客户端））。 客户和服务器所用的Slice 定义建<br>立两者之间的接口合约，这样的定义也是它们唯一需要达成一致的东<br>西。<br>&#8226; 实现无关性<br>客户不知道服务器是怎样实现其对象的。这意味着，在客户部署之<br>后，服务器的实现可以改变，例如，它可以使用不同的持久机制，甚至<br>不同的程序设计语言。<br>&#8226; 操作系统无关性<br>Ice API 完全是可移植的，所以同样的源码能够在Windows 和UNIX<br>上编译和运行。<br>&#8226; 线程支持<br>Ice run time 完全是线程化的，其API 是线程安全的。 作为应用开发<br>者，（除了在访问共享数据时进行同步）你无需为开发线程化的高性能<br>客户和服务器付出额外努力。<br>&#8226; 传输机制无关性<br>Ice 目前采用了TCP/IP 和UDP 作为传输协议。客户和服务器代码都<br>不需要了解底层的传输机制（你可以通过一个配置参数选择所需的传<br>输机制）。<br>&#8226; 位置和服务器透明性<br>Ice run time 会负责定位对象，并管理底层的传输机制，比如打开和<br>关闭连接。客户与服务器之间的交互显得像是无连接的。如果在客户调<br>用操作时，服务器没有运行，你可以通过IcePack 让它们随需启动。服<br>务器可以迁移到不同的物理地址，而不会使客户持有的代理失效，而客<br>户完全不知道对象实现是怎样分布在多个服务器进程上的。<br>&#8226; 安全性<br>通过SSL 强加密，可以使客户和服务器完全安全地进行通信，这<br>样，应用可以使用不安全的网络安全地进行通信。你可以使用Glacier<br>穿过防火墙，实现安全的请求转发，并且完全支持回调。<br>&#8226; 内建的持久机制<br>使用Freeze，创建持久的对象实现变成了一件微不足道的事情。Ice<br>提供了对高性能数据库Berkeley DB[18] 的内建支持。<br>&#8226; 开放源码<br>Ice 的源码是开放的。尽管要使用Ice 平台，并不一定要阅读源码，<br>通过源码你可以了解各种事情是怎样实现的，或把这些代码移植到新的<br>操作系统上。<br>总而言之， Ice 提供了一流的分布式计算开发和部署环境，比我们所知<br>道的其他任何平台都更完整。<br><br><br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 13:38 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice Box</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103392.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 05:36:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103392.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103392.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103392.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103392.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103392.html</trackback:ping><description><![CDATA[IceBox<br>IceBox 是一种简单的应用服务器，可用于协调许多应用组件的启动和停<br>止。应用组件可以作为动态库、而不是进程进行部署。例如，你可以在单<br>个Java 虚拟机中运行若干应用组件，而无需使用多个拥有自己的虚拟机的<br>进程，从而减轻整个系统的负担。<br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103392.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 13:36 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103392.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice 客户与服务器结构</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103384.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 04:06:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103384.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103384.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103384.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103384.html</trackback:ping><description><![CDATA[客户与服务器都由这样一些代码混合而成：应用代码、库代码、根据<br>Slice 定义生成的代码：<br>&#8226; Ice 核心为远地通信提供了客户端和服务器端运行时支持。其中的大量代<br>码所涉及的是网络通信、线程、字节序，以及其他许多与网络有关的问<br>题，我们想要让应用代码与这些问题隔离开来。Ice 核心是作为客户和<br>服务器可与之链接的库提供的。<br>&#8226; Ice 核心的通用部分 （也就是说，与你用Slice 定义的特定类型 无关的部<br>分） 可通过Ice API 访问。你用Ice API 来照管各种管理事务，比如Ice<br>run time 的初始化和结束。用于客户和服务器的Ice API 是一样的 （尽<br>管服务器使用的API 比客户要多）。<br>&#8226; 代理代码是根据你的Slice 定义生成的，因此，与你用Slice 定义的对象和<br>数据的类型是对应的。代理代码有两个主要功能：<br>&#8226; 它为客户提供了一个向下调用（down-call）接口。如果你调用&#8220;生<br>成的代理API&#8221;中的某个函数，就会有一个RPC 消息被发给服务器，<br>调用目标对象上的某个对应的函数。<br>&#8226; 它提供了整编（marshaling）和解编（unmarshaling）代码。<br>整编是使复杂的数据结构（比如序列或词典）序列化、以在线路上进<br>行传送的过程。整编代码把数据转换成适于传送的标准形式，这种形<br>式不依赖于本地机器的"endian-ness" 和填充（padding）规则。<br>解编是整编的逆过程，也就是说，使通过网络到达的数据解除序列<br>化，并且对数据重新进行构造，用与所使用的编程语言相适应的类型<br>来加以表示。<br>&#8226; 骨架（skeleton）代码也是根据你的Slice 定义生成的，因此，与你用<br>Slice 定义的对象和数据的类型是对应的。骨架代码是客户端代理代码<br>的服务器端等价物：它提供了向上调用（up-call）接口，允许Ice run<br>time 把控制线程转交给你编写的应用代码。骨架也含有整编和解编代<br>码，所以服务器可以接收客户发送的参数，并把参数和异常返回给客<br>户。<br>&#8226; 对象适配器（object adapter）是专用于服务器端的Ice API 的一部分：只<br>有服务器才使用对象适配器。对象适配器有若干功能：<br>&#8226; 对象适配器把来自客户的请求映射到编程语言对象上的特定方法。换<br>句话说，对象适配器会跟踪在内存中，都有哪些servant，其对象标识<br>又是什么。<br>&#8226; 对象适配器与一个或多个传输端点关联在一起。如果与某个适配器关<br>联的传输端点不止一个，你可以通过多种传输机制到达在该适配器中<br>的servant。例如，为了提供不同的服务质量和性能，你可以把一个<br>TCP/IP 端点和一个UDP 端点与一个适配器关联在一起。<br>&#8226; 对象适配器要负责创建可以传给客户的代理。对象适配器知道它的每<br>个对象的类型、标识，以及传输机制的详细情况，并且会在服务器端<br>应用代码要求创建代理时在其中嵌入正确的信息。<br>注意，从进程的层面来看，所涉及的进程只有两个：客户与服务器。对<br>分布式通信的所有运行时支持都是由Ice 库以及根据Slice 定义生成的代码<br>提供的（在使用间接代理时，需要使用第三个进程IcePack 来把代理解析<br>为传输端点）。<br><br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 12:06 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice 代理</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103382.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 04:03:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103382.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103382.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103382.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103382.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103382.html</trackback:ping><description><![CDATA[代理（Proxies）<br>要想与某个Ice 对象联系，客户必须持有这个对象的代理1。 代理是客户<br>的地址空间中的一种制品（artifact）；对客户而言，代理就是Ice 对象的<br>代表（该对象可能在远地）。一个代理充当的是一个Ice 对象的本地大使：<br>当客户调用代理上的操作时， Ice run time 会：<br>1. 定位Ice 对象<br>2. 如果Ice 对象的服务器没有运行，就激活它<br>3. 在服务器中激活Ice 对象<br>4. 把所有in 参数传送给Ice 对象<br>5. 等待操作完成<br>6. 把所有out 参数及返回值返回给客户（或在发生错误的情况下抛出异<br>常）<br>代理封装了完成这一系列步骤所必需的全部信息。特别地，代理包含<br>有：<br>&#8226; 寻址信息：用于让客户端run time 联系正确的服务器<br>&#8226; 对象标识：用于确定服务器中的哪一个对象是请求的目标<br>&#8226; 可选的facet 标识符：用于确定代理所引用的是对象的哪一个facet<br><br><br><br><br><br>串化代理（Stringified Proxies）<br>代理中的信息可以用串的形式表示。例如：<br>SimplePrinter:default -p 10000<br>这个字符串表示的是一个代理，我们可以阅读这种表示方式。Ice run<br>time 提供了一些API 调用，允许你把代理转换成它的串化形式，或是进行<br>相反的转换。例如，如果你要把代理存储在数据库表或文本文件中，这种<br>功能会很有用。<br>倘若客户知道某个Ice 对象的标识及其寻址信息，使用这些信息，它可<br>以&#8220;凭空&#8221;创建代理。换句话说，代理内部的所有信息都被认为是透明的<br>；要与某个对象联系，客户只需要知道这个对象的标识、寻址信息，以及<br>对象的类型（为了能调用操作），就可以了。<br><br><br><br>在客户端，接口映射到这样的类：它的成员函数与接口上的操作相对<br>应。考虑下面的简单接口：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;Simple&nbsp;{<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;op();<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">};</span></div>
<br><br>Slice 编译器生成下面的定义，供客户使用：<br><br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;IceProxy&nbsp;{<br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;M&nbsp;{<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Simple;<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;M&nbsp;{<br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Simple;<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;IceInternal::ProxyHandle</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;::IceProxy::M::Simple</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;SimplePrx;<br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;IceInternal::Handle</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;::M::Simple</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;SimplePtr;<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">}<br></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;IceProxy&nbsp;{<br></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;M&nbsp;{<br></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Simple&nbsp;:&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">virtual</span><span style="color: #000000;">&nbsp;IceProxy::Ice::Object&nbsp;{<br></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;::M::SimplePrx&nbsp;ProxyType;<br></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;::M::SimplePtr&nbsp;PointerType;<br></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;op();<br></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;op(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;Ice::Context</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">);<br></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;};<br></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">}</span></div>
<br>(其实我生成的和这个不一样的。。。因为我不适很懂这个东西， 所以根本不敢乱贴)<br><br>在客户的地址空间中， IceProxy::M::Simple 实例是&#8220;远地的服务器<br>中的Simple 接口的实例&#8221;的&#8220;本地大使&#8221;，叫作代理类实例。与服务器端<br>对象有关的所有细节，比如其地址、所用协议、对象标识，都封装在该实<br>例中<br><br>注意， Simple 继承自IceProxy::Ice::Object。这反映了这样一<br>个事实：所有的Ice 接口都隐含地继承自Ice::Object。对于接口中的每个<br>操作，代理类都有两个重载的、同名的成员函数。就前面的例子而言，我<br>们会发现操作op 映射到了两个成员函数op。<br>其中一个函数的最后一个参数的类型是Ice::Context。Ice run time<br>用这个参数存储关于请求的递送方式的信息；你通常并不需要为此提供一<br>个值，可以假装这个参数不存在<br><br><br>客户端应用永远不会直接操纵代理类。事实上，你不允许直接实例化代<br>理类。下面的代码无法编译，因为IceProxy::Simple 含有纯虚的成员<br>函数：<br>IceProxy::Simple s; // Compile-time error!<br>代理实例总是由Ice run time 替客户实例化，所以客户代码永远都不需<br>要直接实例化代理。当客户从run time 那里接收代理时，它会得到指向该<br>代理的代理句柄，其类型是&lt;interface-name&gt;Prx （对于前面的例子<br>就是SimplePrx）。客户通过代理的句柄来访问代理；句柄负责把操作调<br>用转发给其底层的代理，并且会对代理进行引用计数。这意味着，你不会<br>遇到内存管理问题：代理的释放是自动的，会在指向代理的最后一个句柄<br>消失时（退出作用域时）发生。<br>因为应用代码总是使用代理句柄，而决不会直接使用代理类，我们通常<br>既会用代理这个术语来表示代理句柄，也会用它来标识代理类。这反映了<br>这样一个事实：在实际的使用中，代理的&#8220;观感&#8221;就像是底层的代理类实<br>例。如果区分它们很重要，我们会使用术语代理类、代理类实例，以及代<br>理句柄。<br><br><br>代理句柄上的方法 : <br><br>我们在前面的例子中已经看到，句柄实际上是类型为<br>IceInternal::ProxyHandle 的模板，其参数是代理类。这个模板有缺<br>省构造器、复制构造器，以及赋值构造器：<br><br><br>&#8226; 缺省构造器<br>你可以通过缺省方式构造代理句柄。缺省的构造器创建的是哪里也<br>不指向的代理（也就是说，根本不指向对象）。如果你调用这样的null<br>代理上的操作，你会收到<br><br>&#8226; 复制构造器<br>复制构造器负责确保你能根据另一个代理句柄构造出一个代理句<br>柄。在内部，这会使代理的引用计数加一；析构器会使引用计数减一，一旦计数降到零，就释放底层的代理类实例。这样就不会发生内存泄漏<br>了<br><br>赋值操作符<br>你可以随意把一个代理句柄赋给另一个句柄。句柄的实现会保证进<br>行适当的内存管理。自赋值（self-assignment）是安全的，你无需针对<br>这种情况进行保护：<br><br>宽化赋值（Widening assignments）会隐式地进行。例如，如果我们<br>有两个接口Base 和Derived，我们可以隐式地把一个DerivedPrx 变<br>宽成一个BasePrx：<br><br><br>&#8226; 检查转换（checked cast）<br>代理句柄提供了一个checkedCast 方法：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;IceInternal&nbsp;{<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">typename&nbsp;T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ProxyHandle&nbsp;:&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;IceUtil::HandleBase</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Y</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ProxyHandle&nbsp;checkedCast(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;ProxyHandle</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Y</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;r);<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">8</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;};<br></span><span style="color: #008080;">9</span>&nbsp;<span style="color: #000000;">}</span></div>
<br><br><br><br>对于代理来说，检查转换的作用就像是C++ dynamic_cast 相对于<br>指针的作用：它能够让你把基代理赋给派生代理。如果基代理的运行时<br>类型与派生代理的静态类型相容，赋值就能成功，而在赋值之后，基代<br>理代表的对象与派生代理相同。 而如果基代理的运行时类型与派生代理<br>的静态类型不相容，派生代理就会被设成null。下面用一个例子来加以<br>说明：<br><br><br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">BasePrx&nbsp;</span><span style="color: #0000ff;">base</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Initialize&nbsp;base&nbsp;proxy</span><span style="color: #008000;"><br></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">DerivedPrx&nbsp;derived;<br></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">derived&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;DerivedPrx::checkedCast(</span><span style="color: #0000ff;">base</span><span style="color: #000000;">);<br></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(derived)&nbsp;{<br></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Base&nbsp;has&nbsp;run-time&nbsp;type&nbsp;Derived,<br></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;use&nbsp;derived<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Base&nbsp;has&nbsp;some&nbsp;other,&nbsp;unrelated&nbsp;type</span><span style="color: #008000;"><br></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">}<br></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;"></span></div>
<br>表达式DerivedPrx::checkedCast(base) 测试base 指向的<br>是否是 Derived 类型的对象。如果是，则转换成功， derived 指向的<br>对象会被设成与base 指向的相同。否则，转换就会失败，而<br>derived 被设成null 代理。<br>注意， checkedCast 是一个静态方法，所以，要进行向下转换，<br>你总是使用这样的语法：&lt;interface-name&gt;Prx::checkedCast。<br>还要注意，你可以在布尔上下文中使用代理。例如，如果代理不为<br>null， if (proxy) 会返回真<br><br><br>在你调用checkedCast 时，通常会有一条远地消息发往服务器2。<br>这条消息会实际询问服务器：&#8220;这个引用所代表的对象的类型是不是<br>Derived?&#8221;服务器的答复会以成功（非null）或失败（null）的形式传<br>达给应用代码。发送远地消息是必要的，因为作为一条原则，如果没有<br>服务器的确认，客户无法找出代理实际的运行时类型（例如，服务器<br>可能会用一个派生层次更深的对象实现取代现有的某个代理的对象实<br>现）。这意味着，你必须准备好处理checkedCast 失败的情况。例<br>如，如果服务器没有运行，你就会收到ConnectFailedException<br>；如果服务器在运行，但代理所代表的对象已经不存在，你就会收到<br>ObjectNotExistException。<br><br>&#8226; 不检查转换（Unchecked cast）<br>在有些情况下，你知道某个对象支持一个接口，其派生层次比其代<br>理的静态类型的派生层次更深。对于这样的情况，你可以使用不进行检<br>查的向下转换：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;IceInternal&nbsp;{<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">typename&nbsp;T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ProxyHandle&nbsp;:&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;IceUtil::HandleBase</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Y</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ProxyHandle&nbsp;uncheckedCast(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;ProxyHandle</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Y</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;r);<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">8</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;};<br></span><span style="color: #008080;">9</span>&nbsp;<span style="color: #000000;">}</span></div>
<br>只有在你确知代理真的支持派生层次更深的类型时，你才应该使用<br>uncheckedCast：顾名思义， uncheckedCast 不会进行任何检查；<br>它不会联系服务器中的对象，如果失败，它不会返回null （不检查转换<br>在内部的实现就像是C++ static_cast，不会进行任何一种检查）。<br>如果你使用的代理是通过不正确的uncheckedCast 得到的，其行为<br>将是不确定的。你很可能会收到ObjectNotExistException 或<br>OperationNotExistException，但取决于具体情形， Ice run time<br>也可能报告一个异常，说解编失败，甚至还可能会不声不响地返回垃圾<br>结果。<br>尽管有危险， uncheckedCast 仍然是有用的，因为它不用付出向<br>服务器发消息的代价。而且，在初始化过程中（参见第7 章），应用常<br>常会收到静态类型是Ice::Object 的代理，但你知道它的具体的运行<br>时类型。在这样的情况下， uncheckedCast 可以节省发送远地消息<br>的开销。<br><br><br>对象标识与代理比较 : <br><br>代理句柄还支持比较操作&nbsp; ==&nbsp;&nbsp; !=&nbsp; <br><br>这两个操作符允许你比较代理是否相等和不等。为了测试代理是否<br>为null，你可以与直接量0 进行比较，例如：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(proxy&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;"></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;It's&nbsp;a&nbsp;nil&nbsp;proxy</span><span style="color: #008000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #008000;"></span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;It's&nbsp;a&nbsp;non-nil&nbsp;proxy<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #008000;"></span></div>
<br>&#8226; &lt;<br>代理支持operator&lt;。这使得你能把代理放入STL 容器，比如映<br>射表或有序列表。<br>&#8226; 布尔比较<br>代理有一个转换操作符，可以把自己转换成bool。如果代理不是<br>null，这个操作符返回真，否则就返回假。所以你可以编写这样的代<br>码：<br>BasePrx base = ...;<br>if (base)<br>// It's a non-nil proxy<br>else<br>// It's a nil proxy<br>注意，在通过重载的操作符==、!=，以及&lt; 进行代理比较时，会使用<br>代理中的所有信息。这意味着，对象标识不仅要匹配，代理中的其他资料<br>也必须相同，比如协议和端点信息。换句话说，如果你用== 和!= 进行比<br>较，测试的是代理的同一性，而不是对象的同一性<br><br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">Ice::ObjectPrx&nbsp;p1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Get&nbsp;a&nbsp;proxy<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">Ice::ObjectPrx&nbsp;p2&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Get&nbsp;another&nbsp;proxy<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #008000;"></span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(p1&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;p2)&nbsp;{<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;p1&nbsp;and&nbsp;p2&nbsp;denote&nbsp;different&nbsp;objects&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;WRONG!</span><span style="color: #008000;"><br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;"></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;p1&nbsp;and&nbsp;p2&nbsp;denote&nbsp;the&nbsp;same&nbsp;object&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Correct</span><span style="color: #008000;"><br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">}</span></div>
<br>尽管p1 和p2 是不同的，它们代表的可能是同一个Ice 对象。例如，如<br>果p1 和p2 包含了相同的对象标识，但各自使用了不同的协议联系目标对<br>象，就可能会发生上述情况。与此类似，协议可能是一样的，但使用的端<br>点不同（因为单个Ice 对象可以通过若干不同的传输端点联系）。换句话<br>说，如果两个代理用== 比较是相等的，我们就知道这两个代理代表的是同<br>一个对象（因为它们在所有方面都相同）；但如果两个用== 比较不相等，<br>我们什么也不知道：这两个代理所代表的可能是、也可能不是同一个对<br>象。<br>要比较两个代理的对象同一性，你必须使用Ice 名字空间里的一个辅<br>助函数：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;Ice&nbsp;{<br></span><span style="color: #0000ff;">bool</span><span style="color: #000000;">&nbsp;proxyIdentityLess(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;ObjectPrx&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">,<br></span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;ObjectPrx&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">);<br></span><span style="color: #0000ff;">bool</span><span style="color: #000000;">&nbsp;proxyIdentityEqual(</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;ObjectPrx&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">,<br></span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;ObjectPrx&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">);<br>}</span></div>
<br><br>只要嵌在两个代理中的对象标识是一样的， proxyIdentityEqual<br>函数就会返回真，代理中的其他信息会被忽略，比如facet 和传输机制信<br>息。proxyIdentityLess 函数建立了代理的总序（total ordering）。其<br>目的主要是为了让你把对象标识比较用于STL 的有序容器。<br>proxyIdentityEqual 能让你正确地比较代理的 对象标识：<br><br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">Ice::ObjectPrx&nbsp;p1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Get&nbsp;a&nbsp;proxy<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">Ice::ObjectPrx&nbsp;p2&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Get&nbsp;another&nbsp;proxy<img src="http://www.cppblog.com/Images/dot.gif"></span><span style="color: #008000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #008000;"></span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">Ice::proxyIdentityEqual(p1,&nbsp;p2)&nbsp;{<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;"></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;p1&nbsp;and&nbsp;p2&nbsp;denote&nbsp;different&nbsp;objects&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Correct</span><span style="color: #008000;"><br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;"></span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;p1&nbsp;and&nbsp;p2&nbsp;denote&nbsp;the&nbsp;same&nbsp;object&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Correct</span><span style="color: #008000;"><br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">}</span></div>
<br><br> <img src ="http://www.cppblog.com/MemoryGarden/aggbug/103382.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 12:03 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103382.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice Servants</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103383.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 04:03:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103383.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103383.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103383.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103383.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103383.html</trackback:ping><description><![CDATA[Servants<br>&nbsp;Ice 对象是一种具有类型、标识，以及寻址信息<br>的概念性实体。但客户请求最终必须到达具体的服务器端的处理实体，由<br>这样的实体提供操作调用（operation invocation）的行为。换句话说，客户<br>请求最后必须到达服务器，在其内部执行代码，而这些代码用特定的编程<br>语言编写，并在特定的处理器上执行。<br>在服务器端提供操作调用的行为的制品叫作servant。一个servant 提供<br>一个或多个Ice 对象的实质内容（或体现这些对象， incarnate）。实际上，<br>servant 就是服务器开发者编写的类的实例，这些类作为一个或多个Ice 对<br>象的servant、向服务器端run time 进行注册。类的方法对应于Ice 对象的接<br>口上的操作，并且提供这些操作的行为。<br>一个servant 可以只体现一个Ice 对象，也可以同时体现若干Ice 对象。<br>如果是前一种情况， servant 所体现的Ice 对象的标识在这个servant 中是隐<br>含的。如果是后一种情况，在每次收到请求时， servant 也会收到Ice 对象<br>的标识，这样， servant 可以决定在处理该请求期间，体现哪一个对象。<br>反过来，一个Ice 对象也可以拥有多个servant。例如，我们可以为某个<br>Ice 对象创建一个代理，这个对象有两个不同的地址，分别在两台机器上。<br>在这种情况下，我们将拥有两个服务器，每个服务器都有一个servant，但<br>两个servant 体现的是同一个Ice 对象。当客户调用这样的Ice 对象上的操<br>作时，客户端run time 只把请求发给一个服务器。换句话说，使用体现同<br>一个Ice 对象的多个servant，你可以构建冗余的系统：客户端run time 试着<br>把请求发给一个服务器，如果失败，就把请求发给第二个服务器。只有在<br>第二次尝试也失败的情况下，错误才会报告给客户端应用代码。<br><img src ="http://www.cppblog.com/MemoryGarden/aggbug/103383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 12:03 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ice对象  （Ice Object）</title><link>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103373.html</link><dc:creator>memorygarden</dc:creator><author>memorygarden</author><pubDate>Thu, 17 Dec 2009 02:51:00 GMT</pubDate><guid>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103373.html</guid><wfw:comment>http://www.cppblog.com/MemoryGarden/comments/103373.html</wfw:comment><comments>http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103373.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MemoryGarden/comments/commentRss/103373.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MemoryGarden/services/trackbacks/103373.html</trackback:ping><description><![CDATA[Ice 对象（<span style="color: red;">Ice Objects</span>）<br>&nbsp;&nbsp;&nbsp; Ice 对象是一种概念性的实体（或称抽象）。Ice 对象具有以下特征：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8226; Ice 对象是本地或远地的地址空间中、能响应客户请求的实体。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8226; 一个Ice 对象可在单个或多个服务器中实例化（后者是冗余方式）。如果某个对象同时有多个实例，它仍是一个Ice 对象。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8226; 每个Ice对象都有一个或多个接口。 一个接口是一个对象所支持的一系列有名称的操作。客户通过调用操作来发出请求。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8226; 一个操作有零个或更多参数，以及一个返回值。参数和返回值具有明确的类型。参数是有名称的，并且有方向：in 参数由客户初始化，并传给服务器； out 参数由 服务器初始化，并传给客户（返回值只是一种特殊的out 参数）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8226; 一个Ice 对象具有一个特殊的接口，称为它的主接口。此外， Ice 对象还可以提供零个或更多其他接口，称为facets （面）。客户可以在某个对象的各个facets之间进行挑选，选出它们想要使用的接口。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8226; 每个Ice 对象都有一个唯一的对象标识（object identity）。对象标识是用于把一个对象与其他所有对象区别开来的标识值。Ice 对象模型假定对象标识是全局唯一的，也就是说，在一个Ice 通信域中，不会有两个对象具有相同的对象标识。<br><br><br>Ice ObjectProxy&nbsp; 并不是继承自 IceObject 前者是代理的继承层次的根<br>  <img src ="http://www.cppblog.com/MemoryGarden/aggbug/103373.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MemoryGarden/" target="_blank">memorygarden</a> 2009-12-17 10:51 <a href="http://www.cppblog.com/MemoryGarden/archive/2009/12/17/103373.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>