Zeroc ICE中间件号称标准统一,开源,跨平台,跨语言,分布式,安全,服务透明,负载均衡,面向对象,性能优越,防火期穿透,通讯屏蔽。因此相比Corba,DCOM,SOAP,J2EE等的中间件技术,自然是集众多优点于一身,而却没有他们的缺点。 在Windows平台试用了一下Zeroc ICE。运行简单客户端服务器的测试程序,服务器端用C++写的,客户端用C#写的,确实可以互通。使用起来还是非常方便的。
一.ICE文件和生成文件 首先,需要写一个ice文件,如下: //hello.ice //zhouhh //2006.7.21 #ifndef HELLO_ICE #define HELLO_ICE module Demo { interface Hello { //nonmutating 表示不会改变数据成员,相当于C++ 的const //idempotent 表示执行一次和执行多次没有区别。如x=1. nonmutating void sayHello(); idempotent void shutdown();
}; }; #endif 然后在cmd下执行 slice2cpp hello.ice 生成两个文件: Hello.cpp Hello.h // hello.h // Ice version 3.1.0 // Generated from file `Hello.ice' #ifndef __Hello_h__ #define __Hello_h__ #include <Ice/LocalObjectF.h> #include <Ice/ProxyF.h> #include <Ice/ObjectF.h> #include <Ice/Exception.h> #include <Ice/LocalObject.h> #include <Ice/Proxy.h> #include <Ice/Object.h> #include <Ice/Outgoing.h> #include <Ice/Incoming.h> #include <Ice/Direct.h> #include <Ice/StreamF.h> #include <Ice/UndefSysMacros.h> #ifndef ICE_IGNORE_VERSION # if ICE_INT_VERSION / 100 != 301 # error Ice version mismatch! # endif # if ICE_INT_VERSION % 100 < 0 # error Ice patch level mismatch! # endif #endif namespace IceProxy { namespace Demo { class Hello; bool operator==(const Hello&, const Hello&; bool operator!=(const Hello&, const Hello&; bool operator<(const Hello&, const Hello&; bool operator<=(const Hello&, const Hello&; bool operator>(const Hello&, const Hello&; bool operator>=(const Hello&, const Hello&; } } namespace Demo { class Hello; bool operator==(const Hello&, const Hello&; bool operator!=(const Hello&, const Hello&; bool operator<(const Hello&, const Hello&; bool operator<=(const Hello&, const Hello&; bool operator>(const Hello&, const Hello&); bool operator>=(const Hello&, const Hello&); } namespace IceInternal { void incRef(:emo::Hello*); void decRef(:emo::Hello*); void incRef(::IceProxy:emo::Hello*); void decRef(::IceProxy:emo::Hello*); } namespace Demo { typedef ::IceInternal::Handle< :emo::Hello> HelloPtr; typedef ::IceInternal::ProxyHandle< ::IceProxy:emo::Hello> HelloPrx; void __write(::IceInternal::BasicStream*, const HelloPrx&); void __read(::IceInternal::BasicStream*, HelloPrx&); void __write(::IceInternal::BasicStream*, const HelloPtr&); void __patch__HelloPtr(void*, ::Ice::ObjectPtr&); } namespace Demo { } namespace IceProxy { namespace Demo { class Hello : virtual public ::IceProxy::Ice::Object { public: void sayHello() { sayHello(__defaultContext()); } void sayHello(const ::Ice::Context&); void shutdown() { shutdown(__defaultContext()); } void shutdown(const ::Ice::Context&); static const ::std::string& ice_staticId(); private: virtual ::IceInternal::Handle< ::IceDelegateM::Ice::Object> __createDelegateM(); virtual ::IceInternal::Handle< ::IceDelegateD::Ice::Object> __createDelegateD(); }; } } namespace IceDelegate { namespace Demo { class Hello : virtual public ::IceDelegate::Ice::Object { public: virtual void sayHello(const ::Ice::Context&) = 0; virtual void shutdown(const ::Ice::Context&) = 0; }; } } namespace IceDelegateM { namespace Demo { class Hello : virtual public ::IceDelegate:emo::Hello, virtual public ::IceDelegateM::Ice::Object { public: virtual void sayHello(const ::Ice::Context&); virtual void shutdown(const ::Ice::Context&); }; } } namespace IceDelegateD { namespace Demo { class Hello : virtual public ::IceDelegate:emo::Hello, virtual public ::IceDelegateD::Ice::Object { public: virtual void sayHello(const ::Ice::Context&); virtual void shutdown(const ::Ice::Context&); }; } } namespace Demo { class Hello : virtual public ::Ice::Object { public: typedef HelloPrx ProxyType; typedef HelloPtr PointerType; virtual ::Ice::ObjectPtr ice_clone() const; virtual bool ice_isA(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) const; virtual ::std::vector< ::std::string> ice_ids(const ::Ice::Current& = ::Ice::Current()) const; virtual const ::std::string& ice_id(const ::Ice::Current& = ::Ice::Current()) const; static const ::std::string& ice_staticId(); virtual void sayHello(const ::Ice::Current& = ::Ice::Current()) const = 0; ::IceInternal:ispatchStatus ___sayHello(::IceInternal::Incoming&, const ::Ice::Current&) const; virtual void shutdown(const ::Ice::Current& = ::Ice::Current()) = 0; ::IceInternal:ispatchStatus ___shutdown(::IceInternal::Incoming&, const ::Ice::Current&); virtual ::IceInternal:ispatchStatus __dispatch(::IceInternal::Incoming&, const ::Ice::Current&); virtual void __write(::IceInternal::BasicStream*) const; virtual void __read(::IceInternal::BasicStream*, bool); virtual void __write(const ::Ice::OutputStreamPtr&) const; virtual void __read(const ::Ice::InputStreamPtr&, bool); }; void __patch__HelloPtr(void*, ::Ice::ObjectPtr&); } #endif //////////////////////////////////////////////// // hello.cpp // Ice version 3.1.0 // Generated from file `Hello.ice' #include <Hello.h> #include <Ice/LocalException.h> #include <Ice/ObjectFactory.h> #include <Ice/BasicStream.h> #include <Ice/Object.h> #include <IceUtil/Iterator.h> #ifndef ICE_IGNORE_VERSION # if ICE_INT_VERSION / 100 != 301 # error Ice version mismatch! # endif # if ICE_INT_VERSION % 100 < 0 # error Ice patch level mismatch! # endif #endif static const ::std::string __Demo__Hello__sayHello_name = "sayHello"; static const ::std::string __Demo__Hello__shutdown_name = "shutdown"; void IceInternal::incRef(:emo::Hello* p) { p->__incRef(); } void IceInternal::decRef(:emo::Hello* p) { p->__decRef(); } void IceInternal::incRef(::IceProxy:emo::Hello* p) { p->__incRef(); } void IceInternal::decRef(::IceProxy:emo::Hello* p) { p->__decRef(); } void Demo::__write(::IceInternal::BasicStream* __os, const :emo::HelloPrx& v) { __os->write(::Ice::ObjectPrx(v)); } void Demo::__read(::IceInternal::BasicStream* __is, :emo::HelloPrx& v) { ::Ice::ObjectPrx proxy; __is->read(proxy); if(!proxy) { v = 0; } else { v = new ::IceProxy:emo::Hello; v->__copyFrom(proxy); } } void Demo::__write(::IceInternal::BasicStream* __os, const :emo::HelloPtr& v) { __os->write(::Ice::ObjectPtr(v)); } void IceProxy:emo::Hello::sayHello(const ::Ice::Context& __ctx) { int __cnt = 0; while(true) { try { ::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase = __getDelegate(); ::IceDelegate::Demo::Hello* __del = dynamic_cast< ::IceDelegate::Demo::Hello*>(__delBase.get()); __del->sayHello(__ctx); return; } catch(const ::IceInternal::LocalExceptionWrapper& __ex) { __handleExceptionWrapperRelaxed(__ex, __cnt); } catch(const ::Ice::LocalException& __ex) { __handleException(__ex, __cnt); } } } void IceProxy::Demo::Hello::shutdown(const ::Ice::Context& __ctx) { int __cnt = 0; while(true) { try { ::IceInternal::Handle< ::IceDelegate::Ice::Object> __delBase = __getDelegate(); ::IceDelegate::Demo::Hello* __del = dynamic_cast< ::IceDelegate::Demo::Hello*>(__delBase.get()); __del->shutdown(__ctx); return; } catch(const ::IceInternal::LocalExceptionWrapper& __ex) { __handleExceptionWrapperRelaxed(__ex, __cnt); } catch(const ::Ice::LocalException& __ex) { __handleException(__ex, __cnt); } } } const ::std::string& IceProxy::Demo::Hello::ice_staticId() { return ::Demo::Hello::ice_staticId(); } ::IceInternal::Handle< ::IceDelegateM::Ice::Object> IceProxy::Demo::Hello::__createDelegateM() { return ::IceInternal::Handle< ::IceDelegateM::Ice::Object>(new ::IceDelegateM::Demo::Hello); } ::IceInternal::Handle< ::IceDelegateD::Ice::Object> IceProxy::Demo::Hello::__createDelegateD() { return ::IceInternal::Handle< ::IceDelegateD::Ice::Object>(new ::IceDelegateD::Demo::Hello); } bool IceProxy::Demo:perator==(const ::IceProxy::Demo::Hello& l, const ::IceProxy::Demo::Hello& r) { return static_cast<const ::IceProxy::Ice::Object&>(l) == static_cast<const ::IceProxy::Ice::Object&>(r); } bool IceProxy::Demo:perator!=(const ::IceProxy::Demo::Hello& l, const ::IceProxy::Demo::Hello& r) { return static_cast<const ::IceProxy::Ice::Object&>(l) != static_cast<const ::IceProxy::Ice::Object&>(r); } bool IceProxy::Demo:perator<(const ::IceProxy::Demo::Hello& l, const ::IceProxy::Demo::Hello& r) { return static_cast<const ::IceProxy::Ice::Object&>(l) < static_cast<const ::IceProxy::Ice::Object&>(r); } bool IceProxy::Demo:perator<=(const ::IceProxy::Demo::Hello& l, const ::IceProxy::Demo::Hello& r) { return l < r || l == r; } bool IceProxy::Demo:perator>(const ::IceProxy::Demo::Hello& l, const ::IceProxy::Demo::Hello& r) { return !(l < r) && !(l == r); } bool IceProxy::Demo:perator>=(const ::IceProxy::Demo::Hello& l, const ::IceProxy::Demo::Hello& r) { return !(l < r); } void IceDelegateM::Demo::Hello::sayHello(const ::Ice::Context& __context) { ::IceInternal::Outgoing __og(__connection.get(), __reference.get(), __Demo__Hello__sayHello_name, ::Ice::Nonmutating, __context, __compress); bool __ok = __og.invoke(); try { ::IceInternal::BasicStream* __is = __og.is(); if(!__ok) { try { __is->throwException(); } catch(const ::Ice::UserException& __ex) { throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_name()); } } } catch(const ::Ice::LocalException& __ex) { throw ::IceInternal::LocalExceptionWrapper(__ex, false); } } void IceDelegateM::Demo::Hello::shutdown(const ::Ice::Context& __context) { ::IceInternal::Outgoing __og(__connection.get(), __reference.get(), __Demo__Hello__shutdown_name, ::Ice::Idempotent, __context, __compress); bool __ok = __og.invoke(); try { ::IceInternal::BasicStream* __is = __og.is(); if(!__ok) { try { __is->throwException(); } catch(const ::Ice::UserException& __ex) { throw ::Ice::UnknownUserException(__FILE__, __LINE__, __ex.ice_name()); } } } catch(const ::Ice::LocalException& __ex) { throw ::IceInternal::LocalExceptionWrapper(__ex, false); } } void IceDelegateD::Demo::Hello::sayHello(const ::Ice::Context& __context) { ::Ice::Current __current; __initCurrent(__current, __Demo__Hello__sayHello_name, ::Ice::Nonmutating, __context); while(true) { ::IceInternal::Direct __direct(__current); ::Demo::Hello* __servant = dynamic_cast< ::Demo::Hello*>(__direct.servant().get()); if(!__servant) { ::Ice::OperationNotExistException __opEx(__FILE__, __LINE__); __opEx.id = __current.id; __opEx.facet = __current.facet; __opEx.operation = __current.operation; throw __opEx; } try { __servant->sayHello(__current); return; } catch(const ::Ice::LocalException& __ex) { throw ::IceInternal::LocalExceptionWrapper(__ex, false); } } } void IceDelegateD::Demo::Hello::shutdown(const ::Ice::Context& __context) { ::Ice::Current __current; __initCurrent(__current, __Demo__Hello__shutdown_name, ::Ice::Idempotent, __context); while(true) { ::IceInternal::Direct __direct(__current); ::Demo::Hello* __servant = dynamic_cast< ::Demo::Hello*>(__direct.servant().get()); if(!__servant) { ::Ice::OperationNotExistException __opEx(__FILE__, __LINE__); __opEx.id = __current.id; __opEx.facet = __current.facet; __opEx.operation = __current.operation; throw __opEx; } try { __servant->shutdown(__current); return; } catch(const ::Ice::LocalException& __ex) { throw ::IceInternal::LocalExceptionWrapper(__ex, false); } } } ::Ice::ObjectPtr Demo::Hello::ice_clone() const { throw ::Ice::CloneNotImplementedException(__FILE__, __LINE__); return 0; // to avoid a warning with some compilers } static const ::std::string __Demo__Hello_ids[2] = { "::Demo::Hello", "::Ice::Object" }; bool Demo::Hello::ice_isA(const ::std::string& _s, const ::Ice::Current&) const { return ::std::binary_search(__Demo__Hello_ids, __Demo__Hello_ids + 2, _s); } ::std::vector< ::std::string> Demo::Hello::ice_ids(const ::Ice::Current&) const { return ::std::vector< ::std::string>(&__Demo__Hello_ids[0], &__Demo__Hello_ids[2]); } const ::std::string& Demo::Hello::ice_id(const ::Ice::Current&) const { return __Demo__Hello_ids[0]; } const ::std::string& Demo::Hello::ice_staticId() { return __Demo__Hello_ids[0]; } ::IceInternal::DispatchStatus Demo::Hello::___sayHello(::IceInternal::Incoming&, const ::Ice::Current& __current) const { __checkMode(::Ice::Nonmutating, __current.mode); sayHello(__current); return ::IceInternal::DispatchOK; } ::IceInternal::DispatchStatus Demo::Hello::___shutdown(::IceInternal::Incoming&, const ::Ice::Current& __current) { __checkMode(::Ice::Idempotent, __current.mode); shutdown(__current); return ::IceInternal::DispatchOK; } static ::std::string __Demo__Hello_all[] = { "ice_id", "ice_ids", "ice_isA", "ice_ping", "sayHello", "shutdown" }; ::IceInternal::DispatchStatus Demo::Hello::__dispatch(::IceInternal::Incoming& in, const ::Ice::Current& current) { ::std:air< ::std::string*, ::std::string*> r = ::std::equal_range(__Demo__Hello_all, __Demo__Hello_all + 6, current.operation); if(r.first == r.second) { return ::IceInternal::DispatchOperationNotExist; } switch(r.first - __Demo__Hello_all) { case 0: { return ___ice_id(in, current); } case 1: { return ___ice_ids(in, current); } case 2: { return ___ice_isA(in, current); } case 3: { return ___ice_ping(in, current); } case 4: { return ___sayHello(in, current); } case 5: { return ___shutdown(in, current); } } assert(false); return ::IceInternal::DispatchOperationNotExist; } void Demo::Hello::__write(::IceInternal::BasicStream* __os) const { __os->writeTypeId(ice_staticId()); __os->startWriteSlice(); __os->endWriteSlice(); #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug Object::__write(__os); #else ::Ice::Object::__write(__os); #endif } void Demo::Hello::__read(::IceInternal::BasicStream* __is, bool __rid) { if(__rid) { ::std::string myId; __is->readTypeId(myId); } __is->startReadSlice(); __is->endReadSlice(); #if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6 compiler bug Object::__read(__is, true); #else ::Ice::Object::__read(__is, true); #endif } void Demo::Hello::__write(const ::Ice::OutputStreamPtr&) const { Ice::MarshalException ex(__FILE__, __LINE__); ex.reason = "type Demo::Hello was not generated with stream support"; throw ex; } void Demo::Hello::__read(const ::Ice::InputStreamPtr&, bool) { Ice::MarshalException ex(__FILE__, __LINE__); ex.reason = "type Demo::Hello was not generated with stream support"; throw ex; } void Demo::__patch__HelloPtr(void* __addr, ::Ice::ObjectPtr& v) { ::Demo::HelloPtr* p = static_cast< ::Demo::HelloPtr*>(__addr); assert(p); *p = ::Demo::HelloPtr::dynamicCast(v); if(v && !*p) { ::Ice::NoObjectFactoryException e(__FILE__, __LINE__); e.type = ::Demo::Hello::ice_staticId(); throw e; } } bool Demo:perator==(const ::Demo::Hello& l, const ::Demo::Hello& r) { return static_cast<const ::Ice::Object&>(l) == static_cast<const ::Ice::Object&>(r); } bool Demo:perator!=(const ::Demo::Hello& l, const ::Demo::Hello& r) { return static_cast<const ::Ice::Object&>(l) != static_cast<const ::Ice::Object&>(r); } bool Demo:perator<(const ::Demo::Hello& l, const ::Demo::Hello& r) { return static_cast<const ::Ice::Object&>(l) < static_cast<const ::Ice::Object&>(r); } bool Demo:perator<=(const ::Demo::Hello& l, const ::Demo::Hello& r) { return l < r || l == r; } bool Demo::operator>(const ::Demo::Hello& l, const ::Demo::Hello& r) { return !(l < r) && !(l == r); } bool Demo::operator>=(const ::Demo::Hello& l, const ::Demo::Hello& r) { return !(l < r); } ////////////////////////////////////////////// 二。新建项目并配置环境 然后在Visual studio 2003中生成一个win32 console的应用程序,名字叫hello 将两个生成的文件hello.h和hello.cpp加入到项目。 visual studio应该配置好ice的相关目录。 在“工具”->“选项”里面的“项目”->“VC++目录”里配置好“可执行文件”,“库”和“头文件”的ICE路径。 再配置“项目”-“属性” a.在C/C++项里的“运行时库”为多线程DLL(/MD),否则在编译时会出预编译错误: fatal error C1189: #error : "Only multi-threaded DLL libraries can be used with Ice!" b.在"语言"里的“启用运行时类型信息”,选“是/GR”,否则编译时会出警告 warning C4541: “dynamic_cast”用在了带 /GR- 的多态类型“IceDelegate::Ice::Object”上;可能导致不可预知的行为 c.预编译头选“不使用”,并将stdafx.h和stdafx.cpp两个文件去掉,为了兼容性。 d.链接器的“输入”项的“附加依赖项”,填上“ice.lib iceutil.lib”,否则会出一堆下面的错误: error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: void __thiscall IceUtil::Shared::__incRef(void)" (__imp_?__incRef@Shared@IceUtil@@QAEXXZ) ,该符号在函数 "void __cdecl IceInternal::incRef(class IceProxy::FlowCtrlService::MediaGateWayCtrl *)" (?incRef@IceInternal@@YAXPAVMediaGateWayCtrl@FlowCtrlService@IceProxy@@@Z) 中被引用
设置完成后,编译,将所有错误去掉,让编译通过。
三。完成服务器端代码 新建一个类HelloI,从Demo::Hello继承,并实现其两个虚函数 virtual void sayHello(const Ice::Current&) const; virtual void shutdown(const Ice::Current&); 代码如下: //helloi.h //zhouhh //2006.7.21 #ifndef HELLO_I_H #define HELLO_I_H #include <Hello.h> class HelloI : public Demo::Hello { public: virtual void sayHello(const Ice::Current&) const; virtual void shutdown(const Ice::Current&); }; #endif //////////////////////////// //helloi.cpp //zhouhh //2006.7.21 #include <HelloI.h> #include <Ice/Ice.h> using namespace std; void HelloI::sayHello(const Ice::Current&) const { cout << "Hello World!" << endl; } void HelloI::shutdown(const Ice::Current& c) { cout << "Shutting down..." << endl; c.adapter->getCommunicator()->shutdown(); } //////////////////////////////// 至此,接口已经实现完毕。 除了实现接口,还要实现主线程循环。 新建一个类叫HelloServer,从Ice::Application继承,实现其虚函数run(). //helloserver.cpp //zhouhh //2006.7.21 #include <HelloI.h> #include <Ice/Application.h> using namespace std; class HelloServer : public Ice::Application { public: virtual int run(int, char*[]); }; int main(int argc, char* argv[]) { HelloServer app; //app.main会实现一系列自动处理。Ice::Application是一个单件。 return app.main(argc, argv, "config.server"); } int HelloServer::run(int argc, char* argv[]) { //创建对象适配器。对象适配器是servant的容器。一个容器内每个servant的名字都要不一样。 Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Hello"); //将服务程序HelloI new出来,用智能指针存放。注意这是抽象基类的智能指针。 //如果要该类智能指针,可以用typedef IceUtil::Handle<HelloI> HelloIPtr来定义。 ::Demo::HelloPtr hello = new HelloI; //生成服务程序在对象适配器的ID //可以用 = communicator()->stringToIdentity("hello"); //也可以这样写: Ice::Identity id ; id.name = "hello"; //将服务程序加到对象适配器中,让Ice的runtime知道服务程序的存在。 adapter->add(hello, id);//此处会导致智能指针的引用计数加1,所以服务程序实例不会丢失。 adapter->activate(); communicator()->waitForShutdown(); return EXIT_SUCCESS; } ///////////////////////////////////////// 四:客户端创建. //helloClient.cpp //zhouhh //2006.7.21 #include <Ice/Application.h> #include <Hello.h> using namespace std; using namespace Demo; class HelloClient : public Ice::Application { public: virtual int run(int, char*[]); }; int main(int argc, char* argv[]) { HelloClient app; return app.main(argc, argv, "config.client"); } int HelloClient::run(int argc, char* argv[]) { //获取property 智能指针,用于处理config信息 Ice::PropertiesPtr properties = communicator()->getProperties(); //读取property“Hello.Proxy” const char* proxyProperty = "Hello.Proxy"; string proxy = properties->getProperty(proxyProperty); if(proxy.empty()) { cerr << argv[0] << ": property `" << proxyProperty << "' not set" << endl; return EXIT_FAILURE; } //根据配置生成一个代理的智能指针 HelloPrx helloProxy = HelloPrx::checkedCast( communicator()->stringToProxy(proxy)->ice_twoway()->ice_timeout(-1)->ice_secure(false)); if(!helloProxy) { cerr << argv[0] << ": invalid proxy" << endl; return EXIT_FAILURE; } try { helloProxy->sayHello(); } catch(const Ice::Exception& ex) { cerr << ex << endl; } return EXIT_SUCCESS; } 五.配置文件: #config.client #-h 10.130.205.182是远程测试时的配置,本机可以不用。10.130.205.182是服务器运行的地址 Hello.Proxy=hello:tcp -h 10.130.205.182 -p 10000:udp -h 10.130.205.182 -p 10000:ssl -h 10.130.205.182 -p 10001 # # SSL Configuration # #将ice系统目录certs目录下的证书拷到当前目录下。 Ice.Plugin.IceSSL=IceSSL:createIceSSL IceSSL.DefaultDir=certs IceSSL.CertAuthFile=cacert.pem IceSSL.CertFile=c_rsa1024_pub.pem IceSSL.KeyFile=c_rsa1024_priv.pem //////////////////////////// #config.server Hello.Endpoints=tcp -p 10000:udp -p 10000:ssl -p 10001 # # SSL Configuration # #将ice系统目录certs目录下的证书拷到当前目录下。 Ice.Plugin.IceSSL=IceSSL:createIceSSL IceSSL.DefaultDir=certs IceSSL.CertAuthFile=cacert.pem IceSSL.CertFile=c_rsa1024_pub.pem IceSSL.KeyFile=c_rsa1024_priv.pem 至此,一个基于Ice的测试程序就可以运行了!
|
|