轉載網頁:http://blog.csdn.net/liuxuezong/article/details/26745041
一、ICE介紹 ???????? ICE是ZeroC公司開發的一款高效的開源中間件平臺,全稱是Internet Communications Engine。
???????? 它的主要設計目標是:
???????? ? 提供適用于異種環境的面向對象中間件平臺。
???????? ? 提供一組完整的特性,支持廣泛的領域中的實際的分布式應用的開發。
?????? ? ? 避免不必要的復雜性,使平臺更易于學習和使用。
?????? ? ? 提供一種在網絡帶寬、內存使用和 CPU 開銷方面都很高效的實現。
?????? ? ? 提供一種具有內建安全性的實現,使它適用于不安全的公共網絡。
???????? ICE支持多種編程語言:C++、Java、C#、VB、Python、Ruby,也就是說使用ICE時我們可以讓這些語言無縫溝通,不過由于ICE是用C++編寫的,不管用什么語言,你都需要先用C++編譯出一個ICE才行(或者下載已編譯的版本)。
???????? 跨語言的分布式系統首先要定義一個與編程語言無關的接口描述語法,用于分布于各處的服務器與客戶端之間對話。比如DCOM和CORBA使用IDL語法,SOAP使用WSDL語法,當然還有時下流行的JSON。ICE使用的是稱為Slice(Specificatoin Language for Ice)的語法,Slice語法和C++(或Java,C#)比較相近,只要會C++(或Java,C#)很容易就能寫Slice定義了。
二、配置ICE開發環境 ???????? 首先,從http://www.zeroc.com/download.html 下載ICE,目前最新版本是Ice-3.5.1。下載頁面里除了ICE的源碼之外,也提供了VC或C++Builder的已編譯安裝包以及各Linux版本的RPM下載。
???????? 如果下載的是源碼版本,需要編譯的話,最好使用相同版本的編譯器。
1)、ICE需要一些第三方庫,在編譯ICE之前要先編譯第三方庫,清單如下(它們也能在ICE官網上下載):
Berkeley DB
expat
OpenSSL
bzip2
mcpp
2)、編譯完上面這些庫以后,把它們放到同一個目錄中,然后設置用戶環境變量。
???????? ICE_ROOT= D:\Program Files\ZeroC\Ice-3.5.1
3)、把上面編譯好或直接下載的已編譯版本的ice.lib和iceutil.lib(或Debug版本的iced.lib和 iceutild.lib)鏈接入項目即可。
三、ICE的“HelloWorld” ???????? 本文以網上用到比較多的printer經典代碼作為范例說明。
1)、定義接口文件demo.ice [cpp] ?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??? ?? #ifndef?demo_ice ?? ?? #define?demo_ice ?? ?? ?? ?? ?? ?? ?? ?? ??? ?? module?Demo?? ?? {?? ?? ?????????interface?Printer?? ?? ?????????{?? ?? ??????????????void ?printString(string?strMsg);?? ?? ?????????};?? ?? };?? ?? ??? ?? #endif ?? ???????? 它定義一個Printer接口(interface),這個接口只有一個printString方法,輸入參數是一個字符串(string)。最后,這個接口位于Demo模塊(module)之下。
2)、生成接口文件 ???????? 使用slice2cpp程序依據這個Slice定義生成C++使用的頭文件和對應的代理代碼。
>slice2cpp demo.ice
??? 如果沒提示錯誤,就會生成demo.h和demo.cpp,把這兩個文件加入到服務器端項目和客戶端項目后,客戶端就可以向服務器發送消息了。
> slice2java demo.ice
??? 生成java相關代碼,文件較多,這里就不一一寫出了。
> slice2cs demo.ice
??? 生成c#相關代碼只有一份:demo.cs。
3)、Slice與C++的映射關系 Slice
C++
#include
#include
#ifndef
#ifndef
#define
#define
#endif
#endif
module
namespace
bool
bool
byte
Ice::Byte
short
Ice::Short
int
Ice::Int
long
Ice::Long
float
Ice::Float
double
Ice::Double
string
Ice::string
enum
enum(不支持指定數字)
struct
struct
class
class(所有方法都是純虛函數)
interface
struct(所有方法都是純虛函數,沒有成員變量)
sequence<T>
std::vector<T>
dictionary<Key,Value>
std::map<Key,Value>
exception Err
class Err:public Ice:UserException
nonmutating方法限定符
const方法
idempotent方法限定符
-
out 參數限定符
引用類型
*
對應類型的代理類
?? ? ? ? 參考這個表,可以知道上面的Slice定義對應的C++映射如下:
namespace ?Demo
{
?????????struct ?Printer
???????? {
???????????????????virtual ?void ?printString(string strMsg) = 0;
???????? };
};
4)、C++代碼實現 第1步:新建一個控制臺項目democlient;
第2步:將“./;$(ICE_ROOT)\include”添加到“c/c++”->“常規”->“附件包含目錄” 列表中;
圖3-1 包含目錄設置
第3步:將“$(ICE_ROOT)\lib” 添加到“鏈接器”->“常規“->“附件庫目錄”列表中;
圖3-2 附加庫目錄設置
第4步:將“iced.lib”和“iceutild.lib”(debug版本)添加到“鏈接器”->“輸入“-> “附加依賴項”列表中,鏈接入到項目中。
圖3-3 導入靜態庫設置
C++客戶端代碼democlient: [cpp] ?view plaincopy
#include?<ice/ice.h> ?? ?? #include?"demo.h" ?? ?? ??? ?? using ? namespace ?std;?? ?? using ? namespace ?Demo;?? ?? ??? ?? int ?main( int ?argc,? char ?*argv[])?? ?? {?? ?? ?????????Ice::CommunicatorPtr?ic;?? ?? ?????????try ?? ?? ?????????{?? ?? ????????????????????? ?? ???????????????????ic?=?Ice::initialize(argc,argv);?? ?? ????????????????????? ?? ???????????????????Ice::ObjectPrx?base?=ic->stringToProxy("SimplePrinter:default?-p10000" );?? ?? ????????????????????? ?? ???????????????????PrinterPrx?printer?=??PrinterPrx::checkedCast(base);?? ?? ???????????????????if (!printer)?? ?? ???????????????????{?? ?? ????????????????????????????throw ? "InvalidProxy!" ;?? ?? ???????????????????}?? ?? ????????????????????? ?? ???????????????????printer->printString("Hello?World!" );?? ?? ?????????}?? ?? ?????????catch ?( const ?Ice::Exception?&e)?? ?? ?????????{?? ?? ?????????????cerr?<<?e?<<?endl;?? ?? ?????????}?? ?? ?????????catch ?( const ? char ?*msg)?? ?? ?????????{?? ?? ??????????????cerr?<<?msg?<<?endl;?? ?? ?????????}?? ?? ??????????? ?? ?????????if ?(ic)?? ?? ?????????{?? ?? ???????????????????ic->destroy();?? ?? ?????????}?? ?? ?????????return0;?? ?? }?? ??????? 您也可以把服務器端部署到別的電腦上,客戶端代碼改成如下代碼,即可實現遠程調用。
???????? Ice::ObjectPrx base =ic->stringToProxy("SimplePrinter:default -h 127.0.0.1 -p 10000")
C++服務器代碼demoserver: [cpp] ?view plaincopy
#include?"demo.h" ?? ?? ??? ?? using ? namespace ?std;?? ?? using ? namespace ?Demo;?? ?? ??? ?? ?? ?? struct ?CPrinterImp?:?Printer?? ?? {?? ?? ?????????virtual ? void ?printString( const ::std::string&?strMsg,?? ?? ???????????????????const ::Ice::Current&?=?::Ice::Current())?? ?? ?????????{?? ?? ??????????????cout?<<?strMsg?<<?endl;???? ?? ?????????}?? ?? };?? ?? ??? ?? int ?main( int ?argc,? char ?*argv[])?? ?? {?? ?? ?????????Ice::CommunicatorPtr?ic;?? ?? ??? ?? ?????????try ?? ?? ?????????{?? ?? ????????????????????? ?? ???????????????????ic?=?Ice::initialize(argc,argv);?? ?? ????????????????????? ?? ???????????????????Ice::ObjectAdapterPtr?adapter=?ic->createObjectAdapterWithEndpoints(?? ?? ????????????????????????????"SimplePrinterAdapter" ,? "default?-p?10000" );?? ?? ????????????????????? ?? ???????????????????Ice::ObjectPtr?object?=?new ?CPrinterImp;?? ?? ???????????????????adapter->add(object,ic->stringToIdentity("SimplePrinter" ));?? ?? ???????????????????adapter->activate();?? ?? ????????????????????? ?? ???????????????????ic->waitForShutdown();?? ?? ?????????}?? ?? ?????????catch ?( const ?Ice::Exception?&e)?? ?? ?????????{?? ?? ???????????????????cerr?<<?e?<<endl;?? ?? ?????????}?? ?? ?????????catch ?( const ? char ?*msg)?? ?? ?????????{?? ?? ???????????????????cerr?<<?msg?<<endl;?? ?? ?????????}?? ?? ??????????? ?? ?????????if ?(ic)?? ?? ?????????{?? ?? ???????????????????ic->destroy();?? ?? ?????????}?? ?? ?????????return0;?? ?? }?? ???????? 以上代碼編譯通過后,啟動服務端程序。每次調用客戶端后,服務器端會顯示一行
???????? “Hello World!”
5)、java代碼實現
圖3-4 設置ice.jar
??? 從iec3.5.1的lib文件中,把ice.jar添加到工程jar目錄中。
java客戶端代碼democlient: democlient.java 主程序:
[java] ?view plaincopy
public ? class ?democlient?? ?? {?? ?? ????public ? static ? void ?main(String[]?args)?? ?? ????{?? ?? ????????int ?status?=? 0 ;?? ?? ????????Ice.Communicator?ic?=?null ;?? ?? ????????try ?? ?? ????????{?? ?? ?????????????? ?? ????????????ic?=?Ice.Util.initialize(args);?? ?? ????????????? ?? ?????????????? ?? ?????????????? ?? ????????????Ice.ObjectPrx?base?=?ic.stringToProxy(?? ?? ????????????????????"SimplePrinter:default-p?10000" );?? ?? ????????????? ?? ????????????Demo.PrinterPrx?printer?=?Demo.PrinterPrxHelper.checkedCast(base);?? ?? ????????????? ?? ????????????if ?(printer?==? null )?? ?? ????????????{?? ?? ????????????????thrownew?Error("Invalidproxy" );?? ?? ????????????}?? ?? ????????????? ?? ????????????printer.printString("Hello?World!" );?? ?? ????????}???????? ?? ????????catch ?(Ice.LocalException?ex)?? ?? ????????{?? ?? ????????????ex.printStackTrace();?? ?? ????????????status?=?1 ;?? ?? ????????}?? ?? ????????catch ?(Exception?e)?? ?? ????????{?? ?? ????????????System.err.println(e.getMessage());?? ?? ????????????status?=?1 ;?? ?? ????????}?? ?? ????????if ?(ic?!=? null )?? ?? ????????{?? ?? ????????????try ?? ?? ????????????{?? ?? ????????????????ic.destroy();?? ?? ????????????}?? ?? ????????????catch ?(Exception?e)?? ?? ????????????{?? ?? ????????????????System.err.println(e.getMessage());?? ?? ????????????????status?=?1 ;?? ?? ????????????}?? ?? ????????}?? ?? ????????System.exit(status);?? ?? ????}?? ?? }?? java服務端代碼demoserver: PrinterImp.java 接口實現:
[java] ?view plaincopy
public ? class ?PrinterImp? extends ?Demo._PrinterDisp?? ?? {?? ?? ????private ? static ? final ? long ?serialVersionUID?=?1L;?? ?? ??? ?? ????public ? void ?printString(String?strMsg,?Ice.Current?current)?? ?? ????{?? ?? ?????????System.out.println(strMsg);?? ?? ????}?? ?? }?? demoserver.java 主程序:
[java] ?view plaincopy
public ? class ?demoserver?? ?? {?? ?? ????public ? static ? void ?main(String[]?args)?? ?? ????{?? ?? ????????int ?status?=? 0 ;?? ?? ????????Ice.Communicator?ic?=?null ;?? ?? ????????try ?? ?? ????????{?? ?? ?????????????? ?? ????????????ic?=?Ice.Util.initialize(args);?? ?? ????????????? ?? ?????????????? ?? ????????????Ice.ObjectAdapter?adapter?=ic.createObjectAdapterWithEndpoints(?? ?? ????????????????????"SimplePrinterAdapter" ,? "default?-hlocalhost?-p?10000" );?? ?? ????????????? ?? ?????????????? ?? ????????????Ice.Object?object?=?new ?PrinterImp();?? ?? ????????????? ?? ?????????????? ?? ????????????adapter.add(object,?Ice.Util.stringToIdentity("SimplePrinter" ));?? ?? ????????????? ?? ?????????????? ?? ????????????adapter.activate();?? ?? ????????????? ?? ?????????????? ?? ????????????ic.waitForShutdown();???????????? ?? ????????}???????? ?? ????????catch ?(Ice.LocalException?ex)?? ?? ????????{?? ?? ????????????ex.printStackTrace();?? ?? ????????????status?=?1 ;?? ?? ????????}?? ?? ????????catch ?(Exception?e)?? ?? ????????{?? ?? ????????????System.err.println(e.getMessage());?? ?? ????????????status?=?1 ;?? ?? ????????}?? ?? ????????if ?(ic?!=? null )?? ?? ????????{?? ?? ????????????try ?? ?? ????????????{?? ?? ????????????????ic.destroy();?? ?? ????????????}?? ?? ????????????catch ?(Exception?e)?? ?? ????????????{?? ?? ????????????????System.err.println(e.getMessage());?? ?? ????????????????status?=?1 ;?? ?? ????????????}?? ?? ????????}?? ?? ????????System.exit(status);?? ?? ????}?? ?? }?? ???????? java
服務端的程序需要綁定主機 IP ,否則上述語句如果改成這樣: Ice.ObjectAdapteradapter = ic.createObjectAdapterWithEndpoints(
??????????????????? "SimplePrinterAdapter" , "default-p 10000" );
????????? 運行demoserver 之后,會出現如下錯誤:
Ice.SocketException
???? error = 0
???? atIceInternal.Network.doBind(Network.java:251 )
???? atIceInternal.TcpAcceptor.<init>(TcpAcceptor.java:119 )
???? atIceInternal.TcpEndpointI.acceptor(TcpEndpointI.java:414 )
???? atIceInternal.IncomingConnectionFactory.<init>(IncomingConnectionFactory.java:376 )
???? atIce.ObjectAdapterI.<init>(ObjectAdapterI.java:1028 )
???? atIceInternal.ObjectAdapterFactory.createObjectAdapter(ObjectAdapterFactory.java:160 )
???? atIce.CommunicatorI.createObjectAdapterWithEndpoints(CommunicatorI.java:89 )
???? atdemoserver.main(demoserver.java:12 )
Caused by:? java.net.SocketException : Address family not supported by protocol family: bind
???? atsun.nio.ch.Net.bind(Native Method )
???? atsun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:119 )
???? atsun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59 )
???? atIceInternal.Network.doBind(Network.java:245 )
???? ... 7 more
6)、C#代碼實現
圖3-5 添加引用庫ice
democlient.cs主程序: [csharp] ?view plaincopy
using ?System;?? using ?System.Collections.Generic;?? using ?System.Linq;?? using ?System.Text;?? ?? namespace ?democlient?? {?? ????class ?Program?? ????{?? ????????static ? int ?Main( string []?args)?? ????????{?? ????????????int ?status?=?0;?? ????????????Ice.Communicator?ic?=?null ;?? ????????????try ?? ????????????{?? ????????????????ic?=?Ice.Util.initialize(ref ?args);?? ????????????????Ice.ObjectPrx?obj?=?ic.stringToProxy("SimplePrinter:default?-h?localhost?-p?10000" );?? ????????????????Demo.PrinterPrx?printer?=?Demo.PrinterPrxHelper.checkedCast(obj);?? ????????????????if ?(printer?==? null )?? ????????????????{?? ????????????????????throw ? new ?ApplicationException( "Invalid?proxy" );?? ????????????????}?? ?? ????????????????printer.printString("Hello?World!" );?? ????????????}?????????????? ????????????catch ?(Exception?e)?? ????????????{?? ????????????????Console.Error.WriteLine(e);?? ????????????????status?=?1;?? ????????????}?? ????????????if ?(ic?!=? null )?? ????????????{?? ????????????????try ?? ????????????????{?? ????????????????????ic.destroy();?? ????????????????}?? ????????????????catch (Exception?e)?? ????????????????{?? ????????????????????Console.Error.WriteLine(e);?? ????????????????????status?=?1;?? ????????????????}?? ????????????}?? ????????????return ?status;?? ????????}?? ????}?? }?? demoserver.cs主程序: [csharp] ?view plaincopy
using ?System;?? ?? using ?System.Collections.Generic;?? ?? using ?System.Linq;?? ?? using ?System.Text;?? ?? using ?System.Reflection;?? ?? ??? ?? public ? class ?PrinterImpl?:?Demo.PrinterDisp_?? ?? {?? ?? ????public ? override ? void ?printString( string ?strMsg,?Ice.Current?current)?? ?? ????{?? ?? ????????Console.WriteLine(strMsg);?? ?? ????}?? ?? }?? ?? ??? ?? namespace ?demoserver?? ?? {?? ?? ????class ?Program?? ?? ????{?? ?? ????????public ? static ? int ?Main( string []args)?? ?? ????????{?? ?? ????????????intstatus?=?0;?? ?? ????????????Ice.Communicatoric?=?null ;?? ?? ????????????try ?? ?? ????????????{?? ?? ????????????????ic?=?Ice.Util.initialize(refargs);?? ?? ????????????????Ice.ObjectAdapteradapter?=?? ?? ????????????????????ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter" ,? "default?-h?localhost?-p?10000" );?? ?? ????????????????Ice.Objectobj?=?new ?PrinterImpl();?? ?? ????????????????adapter.add(obj,ic.stringToIdentity("SimplePrinter" ));?? ?? ????????????????adapter.activate();?? ?? ????????????????ic.waitForShutdown();?? ?? ????????????}?? ?? ????????????catch ?(Exception?e)?? ?? ????????????{?? ?? ????????????????Console.Error.WriteLine(e);?? ?? ????????????????status?=?1;?? ?? ????????????}?? ?? ????????????if ?(ic?!=? null )?? ?? ????????????{?? ?? ????????????????try ?? ?? ????????????????{?? ?? ????????????????????ic.destroy();?? ?? ????????????????}?? ?? ????????????????catch ?(Exception?e)?? ?? ????????????????{?? ?? ????????????????????Console.Error.WriteLine(e);?? ?? ????????????????????status?=?1;?? ?? ????????????????}?? ?? ????????????}?? ?? ????????????returnstatus;?? ?? ????????}?? ?? ????}?? ?? }?? 四、ICE使用小結 ???????? 本文主要從printer經典的例子入手,綜合使用三種開發語言,驗證ICE在不同語言環境下的使用性如何。從ICE的開發流程上來看,與CORBA開發流程類似。兩者的接口文件定義基本相接近。如果您曾經深入接觸或開發過CORBA組件軟件,那么再入手ICE研究開發工作,將是一件令人愉快的事情,因為它是那么隨心所欲—Easy。
???????? 從企業今后部署的經濟方面考慮,相對于重量級CORBA中間件組件,ICE是開源的、免費的,并且版本還不斷升級。在運行性能與網絡接口處理方面,我們需要測試其穩定性,魯棒性,健壯性等,研究它是否符合企業用戶的業務需求。
頂
1 踩
總結
以上是生活随笔 為你收集整理的浅入ICE组件编程 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。