本文介绍了ICE通信器、对象适配器、Servant定位器以及对象代理的更多使用方法
ICE的整体架构
服务器端:
客户端:
通信器Ice::Communicator
std::string proxyToString(const Ice::ObjectPrx&) const; Ice::ObjectPrx stringToProxy(const std::string&) const;
Ice::ObjectPrx propertyToProxy(const std::string&) const;
Ice::Identity stringToIdentity(const std::string&) const; std::string identityToString(const Ice::Identity&) const;转换字符串到一个对象标识,对象标识的定义如下:
- namespace Ice
- {
- struct Identity
- {
- std::string name;
- std::string category;
- };
- }
Ice::ObjectAdapterPtr createObjectAdapter(const std::string&); Ice::ObjectAdapterPtr createObjectAdapterWithEndpoints( const std::string&, const std::string&);
void shutdown();
void waitForShutdown();
void destroy();
bool isShutdown() const;
初始化通信器
- 属性表(property)
- 日志记录器(Logger)
- 统计对象(Stats)
- 原生字符串与宽字符串转换器
- 线程通知钩子
- namespace Ice {
- struct InitializationData {
- PropertiesPtr properties;
- LoggerPtr logger;
- StatsPtr stats;
- StringConverterPtr stringConverter;
- WstringConverterPtr wstringConverter;
- ThreadNotificationPtr threadHook;
- };
- }
- namespace Ice {
- CommunicatorPtr initialize(int&, char*[],
- const InitializationData& = InitializationData());
- CommunicatorPtr initialize(StringSeq&,
- const InitializationData& = InitializationData());
- CommunicatorPtr initialize(
- const InitializationData& = InitializationData());
- }
- namespace Ice
- {
- struct Application
- {
- int main(int, char*[]);
- int main(int, char*[], const char*);
- int main(int, char*[], const Ice::InitializationData&);
- int main(const StringSeq&);
- int main(const StringSeq&, const char*);
- int main(const StringSeq&, const Ice::InitializationData&);
- ...
- };
- }
- namespace Ice
- {
- class Properties : virtual public Ice::LocalObject
- {
- public:
- virtual std::string getProperty(const std::string&) = 0;
- virtual std::string getPropertyWithDefault(const std::string&,
- const std::string&) = 0;
- virtual Ice::Int getPropertyAsInt(const std::string&) = 0;
- virtual Ice::Int getPropertyAsIntWithDefault(const std::string&,
- Ice::Int) = 0;
- virtual Ice::StringSeq getPropertyAsList(const std::string&) = 0;
- virtual Ice::StringSeq getPropertyAsListWithDefault(const std::string&,
- const Ice::StringSeq&) = 0;
- virtual Ice::PropertyDict getPropertiesForPrefix(const std::string&) = 0;
- virtual void setProperty(const std::string&, const std::string&) = 0;
- virtual Ice::StringSeq getCommandLineOptions() = 0;
- virtual Ice::StringSeq parseCommandLineOptions(const std::string&,
- const Ice::StringSeq&) = 0;
- virtual Ice::StringSeq parseIceCommandLineOptions(const Ice::StringSeq&) = 0;
- virtual void load(const std::string&) = 0;
- virtual Ice::PropertiesPtr clone() = 0;
- };
- };
- namespace Ice
- {
- class Logger : virtual public Ice::LocalObject
- {
- public:
- virtual void print(const std::string& msg) = 0;
- virtual void trace(const std::string& category,
- const std::string& msg) = 0;
- virtual void warning(const std::string& msg) = 0;
- virtual void error(const std::string& msg) = 0;
- };
- }
- namespace Ice
- {
- class Stats : virtual public Ice::LocalObject
- {
- public:
- virtual void bytesSent(const std::string& protocol,
- Ice::Int num) = 0;
- virtual void bytesReceived(const std::string& protocol,
- Ice::Int num) = 0;
- };
- }
- namespace Ice
- {
- class ThreadNotification : public IceUtil::Shared {
- public:
- virtual void start() = 0;
- virtual void stop() = 0;
- };
- }
代码演示
修改一下Helloworld服务器端代码,实现自定义统计对象(Stats,毕竟它最简单嘛-_-):- #include <ice/ice.h>
- #include "printer.h"
- using namespace std;
- using namespace Demo;
- struct PrinterImp : Printer{
- virtual void printString(const ::std::string& s, const ::Ice::Current&)
- {
- cout << s << endl;
- }
- };
- class MyStats : public Ice::Stats {
- public:
- virtual void bytesSent(const string &prot, Ice::Int num)
- {
- cerr << prot << ": sent " << num << "bytes" << endl;
- }
- virtual void bytesReceived(const string &prot, Ice::Int num)
- {
- cerr << prot << ": received " << num << "bytes" << endl;
- }
- };
- class MyApp : public Ice::Application{
- public:
- virtual int run(int n, char* v[]){
- Ice::CommunicatorPtr& ic = communicator();
- ic->getProperties()->parseCommandLineOptions(
- "SimplePrinterAdapter", Ice::argsToStringSeq(n,v));
- Ice::ObjectAdapterPtr adapter
- = ic->createObjectAdapter("SimplePrinterAdapter");
- Ice::ObjectPtr object = new PrinterImp;
- adapter->add(object, ic->stringToIdentity("SimplePrinter"));
- adapter->activate();
- ic->waitForShutdown();
- return 0;
- }
- };
- int main(int argc, char* argv[])
- {
- MyApp app;
- Ice::InitializationData id;
- id.stats = new MyStats;
- return app.main(argc, argv, id);
- }
tcp: send 14bytes tcp: received 14bytes tcp: received 52bytes tcp: send 26bytes tcp: received 14bytes tcp: received 53bytes Hello World! tcp: send 25bytes tcp: received 14bytes
对象适配器(Ice::ObjectAdapter)
- namespace Ice
- {
- struct ObjectAdapter : public LocalObject
- {
- // 返回适配器的名字(由Communicator::createObjectAdapter输入)
- std::string getName() const;
- // 返回创建并拥有应适配器的通信器
- Ice::CommunicatorPtr getCommunicator() const;
- // 激活处于hold状态的适配器。
- void activate();
- // 要求适配器进入hold状态,并马上返回
- void hold();
- // 等待直到适配器进入hold状态
- void waitForHold();
- // 要求适配器进入无效状态,一旦进入无效状态,就无法再次激活它,与该适配器关联的servant将会被销毁。
- void deactivate();
- // 等待直到适配器进入无效状态
- void waitForDeactivate();
- // 如果适配器处于无效状态,返回true
- bool isDeactivated() const;
- // 使适配器处于无效状态,并且释放所有的资源(包括适配器名)
- void destroy();
- // 使用指定的标识把servant注册到适配器中,返回该servant的代理
- Ice::ObjectPrx add(const Ice::ObjectPtr&, const Ice::Identity&);
- // 使用随机生成的UUID作为标识把servant注册到适配器中,返回该servant的代理
- Ice::ObjectPrx addWithUUID(const Ice::ObjectPtr&);
- // 从适配器中移除对应的servant
- Ice::ObjectPtr remove(const Ice::Identity&);
- // 查找对应标识的servant
- Ice::ObjectPtr find(const Ice::Identity&) const;
- // 查找代理对应的servant
- Ice::ObjectPtr findByProxy(const Ice::ObjectPrx&) const;
- // 把一个 Servant Locator 添加到这个对象适配器中。
- void addServantLocator(const Ice::ServantLocatorPtr&, const std::string&);
- // 查找一个已经安装到这个对象适配器中的 Servant Locator。
- Ice::ServantLocatorPtr findServantLocator(const std::string&) const;
- // 创建一个与这个对象适配器及给定标识相匹配的代理
- Ice::ObjectPrx createProxy(const Ice::Identity&) const;
- // 创建一个与这个对象适配器及给定标识相匹配的 " 直接代理 "。
- // 直接代理总是包含有当前的适配器端点。
- Ice::ObjectPrx createDirectProxy(const Ice::Identity&) const;
- // 创建一个与这个对象适配器及给定标识相匹配的 " 间接代理 "。
- // 间接代理只包含对象的标识和适配器名,通过定位器服务来得到服务器地址
- Ice::ObjectPrx createIndirectProxy(const Ice::Identity&) const;
- // 为这个对象适配器设置一个 Ice 定位器
- void setLocator(const Ice::LocatorPrx&);
- // 重新读入适配器的PublicshedEndpoints属性并更新内部的可用网络接口列表
- void refreshPublishedEndpoints();
- };
- }
Servant定位器
- namespace Ice
- {
- class ServantLocator : virtual public Ice::LocalObject
- {
- // 只要有请求到达,而且适配器没有提供注册的条目,Ice就会调用locate。
- // locate的实现(由你在派生类中提供)应该返回一个能够处理该请求的 servant。
- // 通过cookie参数,你可以传入一个自定义指针数据,对象适配器并不在乎这个对象的内容
- // 当Ice 调用finished 时,会把你从locate 返回的cookie传回给你。
- virtual Ice::ObjectPtr locate(const Ice::Current& curr,
- Ice::LocalObjectPtr& cookie) = 0;
- // 一旦请求完成,Ice就会调用finished。
- // 把完成了操作的servant、该请求的Current 对象
- // 以及locate在一开始创建的 cookie 传给它。
- virtual void finished(const Ice::Current& curr,
- const Ice::ObjectPtr& obj, const Ice::LocalObjectPtr& cookie) = 0;
- // 当servant定位器所属的对象适配器无效时,Ice会调用deactivate方法。
- virtual void deactivate(const std::string&) = 0;
- };
- }
- namespace Ice
- {
- struct Current
- {
- // 负责分派当前请求的对象适配器
- Ice::ObjectAdapterPtr adapter;
- //
- Ice::ConnectionPtr con;
- // 当前请求的对象标识
- Ice::Identity id;
- // 请求的 facet
- std::string facet;
- // 正在被调用的操作的名字。
- std::string operation;
- // 操作的调用模式(Normal、Idempotent,或Nonmutating)
- Ice::OperationMode mode;
- // 这个调用的当前上下文,这是一个std::map类型的数据
- // 使用它就允许把数量不限的参数从客户发往服务器
- Ice::Context ctx;
- //
- Ice::Int requestId;
- };
- }
- #include <ice/ice.h>
- #include "printer.h"
- using namespace std;
- using namespace Demo;
- // 原打印版本
- struct PrinterImp : Printer{
- virtual void printString(const ::std::string& s, const ::Ice::Current&)
- {
- cout << s << endl;
- }
- };
- // OutputDebugString版本
- struct DbgOutputImp : Printer{
- virtual void printString(const ::std::string& s, const ::Ice::Current&)
- {
- ::OutputDebugStringA(s.c_str());
- }
- };
- // MessageBox版本
- struct MsgboxImp : Printer{
- virtual void printString(const ::std::string& s, const ::Ice::Current&)
- {
- ::MessageBoxA(NULL,s.c_str(),NULL,MB_OK);
- }
- };
- struct MyLocator : Ice::ServantLocator{
- virtual Ice::ObjectPtr locate(const Ice::Current& curr,
- Ice::LocalObjectPtr& cookie)
- {
- if(curr.id.name == "Dbg")
- return Ice::ObjectPtr(new DbgOutputImp);
- else if(curr.id.name == "Msg")
- return Ice::ObjectPtr(new MsgboxImp);
- else if(curr.id.name == "SimplePrinter")
- return Ice::ObjectPtr(new PrinterImp);
- else
- return NULL;
- }
- virtual void finished(const Ice::Current& curr,
- const Ice::ObjectPtr& obj, const Ice::LocalObjectPtr&)
- {
- }
- virtual void deactivate(const std::string& category)
- {
- }
- };
- class MyApp : public Ice::Application{
- public:
- virtual int run(int n, char* v[]){
- Ice::CommunicatorPtr& ic = communicator();
- ic->getProperties()->parseCommandLineOptions(
- "SimplePrinterAdapter", Ice::argsToStringSeq(n,v));
- Ice::ObjectAdapterPtr adapter
- = ic->createObjectAdapter("SimplePrinterAdapter");
- Ice::ObjectPtr object = new PrinterImp;
- adapter->add(object, ic->stringToIdentity("SimplePrinter"));
- // 注册MyLocator定位器,负责返回category为"Loc"的相应servant。
- adapter->addServantLocator(Ice::ServantLocatorPtr(new MyLocator),"Loc");
- adapter->activate();
- ic->waitForShutdown();
- return 0;
- }
- };
- int main(int argc, char* argv[])
- {
- MyApp app;
- return app.main(argc, argv);
- }
--MyProp.Printer="Loc/Msg:tcp -p 10000"
对象代理(Object Proxy)
示例代码:- Filesystem::FilePrx myFile = ...;
- FileSystem::FilePrx timeoutFile
- = FileSystem::FilePrx::uncheckedCast(
- myFile->ice_timeout(5000));
- try {
- Lines text = timeoutFile->read(); // Read with timeout
- } catch(const Ice::TimeoutException &) {
- cerr << "invocation timed out" << endl;
- }
- Lines text = myFile->read(); // Read without timeout
- Ice::ObjectPrxo=communicator->stringToProxy(/* ... */);
- // Get a oneway proxy.
- Ice::ObjectPrx oneway = o->ice_oneway();
- // Down-cast to actual type.
- PersonPrx onewayPerson = PersonPrx::uncheckedCast(oneway);
- // Invoke an operation as oneway.
- try {
- onewayPerson->someOp();
- } catch (const Ice::TwowayOnlyException &) {
- cerr << "someOp() is not oneway" << endl;
- }
- Ice::ObjectPrxo=communicator->stringToProxy(/* ... */);
- // Get a datagram proxy.
- //
- Ice::ObjectPrx datagram;
- try {
- datagram = o->ice_datagram();
- } catch (const Ice::NoEndPointException &) {
- cerr << "No endpoint for datagram invocations" << endl;
- }
- // Down-cast to actual type.
- //
- PersonPrx datagramPerson = PersonPrx::uncheckedCast(datagram);
- // Invoke an operation as a datagram.
- //
- try {
- datagramPerson->someOp();
- } catch (const Ice::TwowayOnlyException &) {
- cerr << "someOp() is not oneway" << endl;
- }
批量调用代理:
Ice::ObjectPrx ice_batchOneway() const; Ice::ObjectPrx ice_batchDatagram() const; void ice_flushBatchRequests();示例代码:
- Ice::ObjectPrx base = ic->stringToProxy(s);
- PrinterPrx printer = PrinterPrx::uncheckedCast(base->ice_batchOneway());
- if(!printer) throw "Invalid Proxy!";
- printer->printString("Hello");
- printer->printString("World");
- printer->ice_flushBatchRequests();