Ice笔记--服务端的Slice-to-C++
来源:互联网 发布:淘宝店招导航全屏代码 编辑:程序博客网 时间:2024/05/21 22:50
一、初始化和结束服务器端Ice run time
初始化和结束服务器端Ice run time的实现可分为三种方式:常用main函数实现,利用Ice::Application类实现,利用Ice::Service类等。
1)服务端main函数
1.1)初始化Ice run time
Ice run time 的主要进入点是由本地接口Ice::Communicator表示,在程序的开始必须首先调用Ice::Initialize对Ice run time 进行初始化;Ice::Communicator返回一个智能指针,指向一个 Ice::Communicator实例。
初始化的代码在服务端main函数实现大致如:Ice::CommunicatorPtr ic = Ice::initialize(argc , argv); 。如果在初始化过程中出了任何问题,Ice::initialize 会抛出异常。
1.2)结束Ice run time
在离开main函数之前,必须调用Communicator::destroy来结束Ice run time 。 destroy会等待任何正在运行的操作调用完成;如果在调用destroy函数之前就终止main函数,会导致不确定的后果。
1.3)服务器main函数类似实现如下:
#include <Ice/Ice.h>int main(int argc, char * argv[]){ int status = 0; Ice::CommunicatorPtr ic; //这段代码把对Ice::initialize 的调用放在了try 块中,并且会负责把正确的退出状态返回给操作系统 try { ic = Ice::initialize(argc, argv); // Server code here... } catch (const Ice::Exception & e) { cerr << e << endl; status = 1; } catch (const std::string & msg) { cerr << msg << endl; status = 1; } catch (const char * msg) { cerr << msg << endl; status = 1; } if (ic) { ic->destroy(); } return status;}
2)Ice::application类
由于上述的main函数结构很常用,所以有必要将这些操作封装起来。 Ice::application类则封装了所有正确的初始化和结束活动。
2.1)application类定义
namespace Ice{ class Application { public: Application(); virtual ~Application(); int main(int, char * [], const char * = 0); virtual int run(int, char * []) = 0; static const char * appName(); static CommunicatorPtr communicator(); // ... };}
2.2)实现并使用继承自Ice::application的子类
Ice::Application 能够确保你的程序适当地结束Ice run time,不管服务器是正常终止,还是因为对异常或信号作出响应而终止的。因此建议在所有应用程序中使用这个类。
其程序代码的实现大致如下:
#include <Ice/Ice.h> class MyApplication : virtual public Ice::Application {public: virtual int run(int, char * []) { // Server code here... return 0; }}; int main(int argc, char * argv[]){ MyApplication app; return app.main(argc, argv);}
2.3)使用Ice::Service类
相对于Ice::application类来说,建议使用Ice::Service的情况会比较少。当应用可能需要作为Unix 看守(daemon)或Win32 服务运行在系统一级时,Ice::Service可以提供相关功能实现。
这里不再详细介绍Ice::Service。详细资料可以参考 《Ice-1.3.0_cn.pdf》第10章中的内容。
二、接口的映射
1)骨架类
在客户端,接口映射到代理类(参见5.12 节)。在服务器端,接口映射到骨架类。对于相应的接口上的每个操作,骨架类都有一个对应的纯虚方法。
例如,有一个Node接口的定义:
module Filesystem{ interface Node { nonmutating string name(); }; // ...};
Slice 编译器为这个接口生成这样的定义:
namespace Filesystem{ class Node : virtual public Ice::Object { public: virtual std::string name(const Ice::Current & = Ice::Current()) const = 0; // ... }; // ...}
下面是骨架类的几点特性:
• 和客户端一样,Slice 模块映射到名字相同的C++ 名字空间,所以骨架类定义会放在名字空间Filesystem 中。
• 骨架类的名字与Slice 接口的名字(Node)相同。
• 对于Slice 接口中的每个操作,骨架类都有一个对应的纯虚成员函数。
• 骨架类是抽象基类,因为它的成员函数是纯虚函数。
• 骨架类继承自Ice::Object (这个类形成了Ice 对象层次的根)。
2)Servant类
要给Ice 对象提供实现,我们必须创建servant 类,继承对应的骨架类。例
如,要为Node 接口创建servant,可以编写:
#include <Filesystem.h> // Slice-generated headerclass NodeI : public virtual Filesystem::Node{public: NodeI(const std::string &); virtual std::string name(const Ice::Current &) const;private: std::string _name;};
2.1)实例化servant
首先在堆上创建一个显得NodeI实例,把它的地址赋值给类型为NodeIPtr的智能指针:
typedef IceUtil::Handle<NodeI> NodeIPtr; NodeIPtr servant = new NodeI("Fred");
使用智能指针的好处是避免偶然发生内存泄露。
2.2)创建标识
每一个Ice对象都需要一个标识。在使用同一个对象适配器的所有servant中,该标识必须是唯一的。Ice 对象标识是一种结构,下面是它的Slice 定义:
module Ice{ struct Identity {//对象的完整标识由Identity 的name 和category 域组成 string name; string category; }; // ...};
2.3)激活servant
只有在你显式地把servant 告知对象适配器之后, Ice run time 才会知道这个servant 的存在。要激活servant,就要调用对象适配器的add 操作:
void activateServant(const string & name){ NodePtr servant = new NodeI(name); // Refcount == 1 Ice::Identity id; id.name = name; _adapter->add(servant, id); // Refcount == 2} // Refcount == 1
调用对象适配器的add 操作,会把servant 指针和servant 的标识增加到适配器的servant 映射表中,并把“Ice 对象的代理”与“服务器内存中的正确的servant 实例”链接在一起。
同时Ice也提供了addwithUUID()函数,只要一步,就可以生成一个UUID、并把servant 增加到servant 映射表中。这样就避免了额外创建标识的操作。重写上面的函数
void activateServant(const string & name){ NodePtr servant = new NodeI(name); _adapter->addWithUUID(servant);}
2.4)创建代理
一旦我们激活了Ice 对象的servant,服务器就可以处理针对这个对象的客户请求了。但是,只有拥有了对象的代理,客户才能访问该对象。
而象适配器含有创建代理所需的全部详细资料:寻址信息和协议信息,还有对象标识。对象适配器的add 和addWithUUID servant 激活操作会返回对应的Ice 对
象的一个代理。这意味着,我们可以编写:
typedef IceUtil::Handle<NodeI>NodeIPtr;NodeIPtr servant = new NodeI(name);NodePrx proxy = NodePrx::uncheckedCast(_adapter->addWithUUID(servant));// Pass proxy to client...
在此我们需要使用uncheckedCast,因为addWithUUID 返回的代理的类型是Ice::ObjectPrx。
三、传递参数和抛出异常
1)参数传递
服务器端的参数传递所遵循的规则和客户端一样:
• in 参数通过值或const 引用传递。
• out 参数通过引用传递。
• 返回值通过值传递。
例子说明:
interface Example{ string op(string sin, out string sout);};为这个接口生成的骨架类:
class Example : virtual public ::Ice::Object{public: virtual std::stringop(const std::string &, std::string &, const Ice::Current & = Ice::Current()) = 0; // ...};
2)引发异常
要从操作实现中抛出异常,你只需实例化异常,初始化,然后抛出它。例如:
void Filesystem::FileI::write(const Filesystem::Lines & text,const Ice::Current &){ // Try to write the file contents here... // Assume we are out of space... if (error) { Filesystem::GenericError e; e.reason = "file too large"; throw e; }};
- Ice笔记--服务端的Slice-to-C++
- ICE的slice定义注意事项
- ICE的slice定义注意事项
- ICE学习笔记(01):Slice规范
- ICE学习笔记(01):Slice规范
- ice slice The Slice Language
- ICE笔记(03):客户端Slice到C++映射
- ICE笔记(05):服务器端Slice到C++映射
- Ice 读书笔记--Slice语言
- Ice 读书笔记--Slice语言
- ice slice Forward Declarations
- zeroc ice slice文件中的一个小小的使用细节
- Ice学习--简单的例子(服务端)
- Ice笔记--Ice的服务器实现技术
- ICE Manual(Documentation for Ice 3.5)---Slice
- ZeroC ICE之旅------Slice
- ICE:slice语言常识整理
- zeroC ice slice 语法总结
- 二维数组保存字符串应用(杭电acm1004)
- Apache Solr 初级教程(介绍、安装部署、Java接口、中文分词)
- ListView 浅析
- ASP.NET自定义Web服务器控件-login登录控件
- 如何做Web上的用户登录功能
- Ice笔记--服务端的Slice-to-C++
- 子进程 信息显示
- javascript Lazyload
- 使用Z-Bias解决Z-Fighting问题的替代方案 Alternatives to Using Z-Bias to Fix Z-Fighting Issues
- Velcro实施小结-20110825
- pcie设备核心请求四种空间访问
- 跟我一起写Makefile(1)
- 改变CListCtrl某行的颜色
- iphone一些知识,去掉StatusBar,横屏,重力感应,自动切换横竖,开机画面横屏,开机画面横屏。