一) 名词
ICE的语法规则
ICE的版本控制(Facet)
持久化 (Feeze)
服务装箱管理 (ICEBox)
文件分发(ICEPatch2)
发布/订阅 服务(ICEStorm)
网络拓扑负载解决方案–终极武器(ICEGrid)
提供使用安全传输入协议SSL的插件(IceSSL)
轻量级的ICE应用防火墙其解决方案(Galcier2)
二)开发流程
1)一般开发过程为,先用ICE 接口描述语言写好接口。
2)使用工具将接口描述文档转成对应语言的代码,转出的代码又分为服务端与客户端代码
工具有以下几种:
slice2cpp slice2freeze slice2freezej slice2html slice2java slice2php sliceprint
3)用户实现自己的需求
三) 文档
https://doc.zeroc.com/display/Ice36/Ice+Manual
四) [下面的是转载] ICE的整体架构
服务器端:
服务器端通常只有一个通信器(Ice::Communicator),通信器包含了一系列的资源:
如线程池、配置属性、对象工厂、日志记录、统计对象、路由器、定位器、插件管理器、对象适配器
在通信器内,包含有一个或更多的对象适配器(Ice::ObjectAdapter),对象适配器负责提供一个或多个传输端点,并且把进入的请求分 派到对应的servant中去执行。
具体实现的部分称为servant,它们为客户端发来的调用提供服务。servant向对象适配器注册以后,由对象适配器依据客户请求调用相应方 法。
客户端:
客户端直接通过代理进行远程调用,就象本地调用一样简单。
通信器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 getPropertyAsIntWithDefa ult(const std::string&, -
Ice::Int) = 0; -
virtual Ice::StringSeq getPropertyAsList(const std::string&) = 0; -
virtual Ice::StringSeq getPropertyAsListWithDef ault(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 parseIceCommandLineOptio ns(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)
对象适配器负责提供一个或多个传输端点,并且把进入的请求分派到对应的servant中去执行。它的定义以及主要方法有:
- 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 refreshPublishedEndpoint s(); - };
- }
Servant定位器
除直接向对象适配器注册servant以外,Ice允许我们向对象适配器提供一个Servant定位器。
有了Servant定位器以后,对象适配器得到一次请求时首先查找已注册的servant,如果没找到对应的servant,就会请求 Servant定位器提供servant。
采用这种简单的机制,我们的服务器能够让我们访问数量不限的servant:服务器不必为每一个现有的Ice对象实例化一个单独的 servant。
下面是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; - };
- }
实现了ServantLocator后,通过对象适配器的addServantLocator方法注册到该适配器中。
在上面的接口中,有一个Ice::Current结构类型的参 数,通过它,我们就可以访问“正在执行的请求”和“服务器中的操作的实现”等信息,Ice::Current的 定义如下:
- 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; - };
- }
利用Ice::Current的id成员,我们可以得到所请求的对象标识,从而决定生产某个具体的 Servant;使用ctx成员,我们还可以从客户端发送数据不限的 “键值-数值”对到服务器中,实现灵活控制(甚至连方法参数都可以不用了,全部用ctx转送就行)。
例:向原HelloWorld 版服务器加入Servant定位器代码,当请求的标识的category为”Loc“时,由定位器返回对应的 servant。
服务器端
- #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); - }
客户端代码与《ICE属性配置》 中的代码相同,客户端命令行参数为
--MyProp.Printer="Loc/Msg:tcp -p 10000"
服务器端将会使用对话框显示“HelloWorld”。
对象代理(Object Proxy)
ice_timeout方法,声明为:Ice::ObjectPrx ice_timeout(int) const;返回一个超时代理,当在指定的 时间(单位毫秒)内没有得到服务器端响应时,操作终止并抛出Ice::TimeoutException异常。
示例代码:
- 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_oneway方法,声明为:Ice::ObjectPrx ice_oneway() const;返回一个单向调用代理。只要数据从本地 端口发送出去,单向调用代理就认为已经调用成功。这意味着,单向调用是不可靠的:它可能根本没有发送出去 (例如,因为网络故障) ,也可能没有被服务器接受(例如,因为目标对象不存在)。好处是由于不用等服务端回复,能带来很大的效率提升。
示例代码:
- 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_datagram方法,声明为:Ice::ObjectPrx ice_datagram() const;返回数据报代理,它使用UDP传输 机制,并且和单向调用代理一样,不会得到服务器端的答复,而且还有可能UDP包重复和不按次序到达服务端。
示例代码:
- 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对象代理提供了ice_batchOneway和ice_batchDatagram方法返回对应的批调用代理,使用这种代理时呼 叫信息不会马上发出,而是等到调用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();
今天的文章ice学习系统 1 ice 中的基本概念[通俗易懂]分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/89398.html