`

ICE笔记(05):服务器端Slice到C++映射

 
阅读更多

colorado

本文将介绍服务器端的Slice到C++ 映射。客户端Slice到C++映射的内容也适用于服务器端。

1、服务器端的主要流程
从ICE的Hello World应用程序中可以看到,Ice运行时的主入口点为Ice::Communicator。程序必须首先调用Ice::initialize,对Ice运行时进行初始化。Ice::initialize 返回一个指向Ice::Communicator实例的智能指针。根据该指针调用Ice提供的各种服务,实现各项功能。

当关闭Ice程序时,必须调用Communicator::destroy。destroy会确保还在执行的操作完成调用,收回操作系统资源,如果未调用destroy 就终止程序;这样做会导致不确定的行为。

整个流程结构是公式化的代码,Ice提供了Ice::Application 类,封装了Ice运行时的初始、销毁操作。此后,我们将主要使用Ice:Application类,以减少编码工作。

2、Ice::Application类
Applicaiton类的使用:
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);
}


Application类的定义:
namespace Ice {
enum SignalPolicy { HandleSignals, NoSignalHandling };
class Application /* ... */ {
public:
Application(SignalPolicy = HandleSignals);
virtual ~Application();

int main(int argc, char*[] argv);
int main(int, char*[], const char* config);
int main(int argc, char*[] argv,const Ice::InitializationData& id);
int main(const Ice::StringSeq&);
int main(const Ice::StringSeq&, const char* config);
int main(const Ice::StringSeq&,const Ice::InitializationData& id);

virtual int run(int, char*[]) = 0;

static const char* appName();
static CommunicatorPtr communicator();
// ...
};
}


Application::main 函数的功能:
⑴. 安装了Ice::Exception异常处理器。Ice异常失败,打印到stderr。
⑵. 安装了const std::string & 和const char * 异常处理器。致命错误情况打印到stderr。
⑶. 初始化(通过调用Ice::initialize)和结束(通过调用Communicator::destroy)通信器。用communicator() 访问通信器。
⑷. 处理并删除Ice相关参数,传给run 方法的参数向量只与特定应用程序相关。
⑸. appName返回argv[0],应用程序名。
⑹. 创建了IceUtil::CtrlCHandler,处理中止信号。
⑺. 安装了每进程日志器。以Ice.ProgramName为前缀,日志输出stderr。使用InitializationData结构,可以指定日志器。

Application 类捕获信号的操作:
namespace Ice {
class Application : /* ... */ {
public:
// ...
static void destroyOnInterrupt();
static void shutdownOnInterrupt();
static void ignoreInterrupt();
static void holdInterrupt();
static void releaseInterrupt();
static bool interrupted();

virtual void interruptCallback(int);
};
}

IceUtil::CtrlCHandler 类中封装了平台无关的信号处理能力。
Unix:SIGINT、SIGHUP,SIGTERM;
Windows:CTRL_C_EVENT、CTRL_BREAK_EVENT、CTRL_CLOSE_EVENT、CTRL_LOGOFF_EVENT,CTRL_SHUTDOWN_EVENT。

destroyOnInterrupt:
创建IceUtil::CtrlCHandler,当信号产生时销毁通讯器。这是缺省行为。

shutdownOnInterrupt:
创建IceUtil::CtrlCHandler,当信号产生时关闭通讯器。

ignoreInterrupt:
忽略信号

callbackOnInterrupt:
信号发生时,Ice::Application调用interruptCallback,以便子类处理信号 。如果信号处理器要终止程序,必须调用_exit,而不是exit。

holdInterrupt:
阻塞信号

releaseInterrupt:
发送被阻塞的信号

interrupted:
信号关闭了通讯器,返回true;否则返回false,表示正常有关闭。

interruptCallback
子类重写本函数,响应信号。


MyApplication app; //或app(HandleSignals); 默认处理信号
MyApplication app(NoSignalHandling); //不处理信号

如果服务器被信号中断,Ice运行时会等待目前正在执行的所有操作完成。才会完成信号处理。
Application负责用属性值初始化Ice运行时,它是单例类,创建单个通信器。如果要创建多个通讯器,必须使用类似Ice的Hello World程序那样的常规代码结构。

3、Ice::Service 类
类似Application类,可以作为系统服务运行。要实现这项功能,至少要重写start类。
Service类的使用:
#include <Ice/Service.h>
class MyService : public Ice::Service {
protected:
virtual bool start(int, char * []);
private:
Ice::ObjectAdapterPtr _adapter;
};
bool MyService::start(int argc, char * argv[])
{
_adapter = communicator()->createObjectAdapter("MyAdapter");
_adapter->addWithUUID(new MyServantI);
_adapter->activate();
return true;
}
int main(int argc, char * argv[])
{
MyService svc;
return svc.main(argc, argv);
}

Service类的定义:
namespace Ice {
class Service {
public:
Service();
virtual bool shutdown();
virtual void interrupt();

int main(int&, char*[],const Ice::InitializationData&=Ice::InitializationData());
int main(Ice::StringSeq&,const Ice::InitializationData&=Ice::InitializationData());
Ice::CommunicatorPtr communicator() const;

static Service * instance();

bool service() const;
std::string name() const;
bool checkSystem() const;

int run(int&, char*[], const Ice::InitializationData&);
void configureService(const std::string&);
void configureDaemon(bool, bool, const std::string&);
virtual void handleInterrupt(int);

protected:
virtual bool start(int, char * []) = 0;
virtual void waitForShutdown();
virtual bool stop();
virtual Ice::CommunicatorPtr initializeCommunicator(int &,char * [],
const Ice::InitializationData&);
virtual void syserror(const std::string &);
virtual void error(const std::string &);
virtual void warning(const std::string &);
virtual void trace(const std::string &);

void enableInterrupt();
void disableInterrupt();
// ...
};
}

Service.main
⑴、分析处理参数向量
⑵、配置configureService/configureDaemon
⑶、运行run

Service.run
⑴、安装CtrlCHandler处理信号
⑵、初始化通讯器
⑶、调用start
⑷、调用waitForShutdown
⑸、调用stop
⑹、销毁通讯器
⑺、得体地终止服务

Service成员函数:
handleInterrupt
信号发生时由CtrlCHandler调用,缺省忽略信号。

initializeCommunicator
初始化通讯器,缺省Ice::initialize

interrupt
信号处理器调用它表示收到信号, 缺省实现调用shutdown。

shutdown
关闭服务器

start
启动:参数处理,创建对象适配器,注册服务者……

stop
终止之前的清理

syserror,error,warning,trace,print 将消息记录到通讯器日志器中。

waitForShutdown
等待服务关闭,缺省实现是调用通讯器的waitForShutdown。

checkSystem:
支持服务,返回true。

disableInterrupt
禁用信号

enableInterrupt
启用信号,handleInterrupt处理

configureDaemon
configureService

*instance
服务实例

name
服务名称

run
必须设置configureDeamon/configService作为服务运行。

service
是服务,返回true。

日志
Windows上,不设置日志器,会记录到系统事件日志中。
Unix上,使用Ice.UseSyslog指日志器,Ice.StdErr将错误重定向到文件。

命令行参数:
Unix平台上 --daemon参数指明程序应该作为守护程序运行。
Windows平台上 --service NAME参数指明程序作为NAME服务运行。

有关Ice::Application和Ice::Service 相关信息还可以参考ydogg 博客的相关文章。

4、接口映射
在客户端,接口映射到代理类。在服务器端,接口映射到骨架类。骨架类是抽象类,成员函数为纯虚函数,继承自Ice::Object。

服务者类
服务者类继承并实现对应的骨架类。在定义服务者类时建议总是使用虚继承。严格地说,只有其实现的接口使用了多继承的服务者才必须使用虚继承;但virtual关键字并无害处,同时,如果在开发中途要给接口层次增加多继承,无需回去给服务者类增加virtual 关键字。

5、参数传递
Slice规范的操作:
string op(string sin, out string sout);

C++映射代码:
virtual std::string op(const std::string &, std::string &,const Ice::Current & = Ice::Current()) = 0;

• in 参数通过值或const 引用传递。
• out 参数通过引用传递。
• 返回值通过值传递。
• 在Slice规范中["cpp:const"]指令可以指定const成员函数。

6、异常
异常:只抛出Slice异常规范中定义的异常。
抛C++异常,客户会收到UnknownException;
抛未在异常规范中定义的用户异常,客户会收到UnknownUserException;
抛Ice运行时异常,客户会收到UnknownLocalException。

7、激活服务者
NodePtr servant = new NodeI(name);
Ice::Identity id;
id.name = name;
MyAdapter->add(servant, id);

⑴. 实例化服务者类
在堆上创建NodeI实现类,赋给智能指针servant。如果要调用NodeI类的成员函数,应该定义NodeIPtr智能指针:
typedef IceUtil::Handle<NodeI> NodeIPtr;
NodeIPtr servant = new NodeI(name);

⑵. 服务者对应的Ice对象创建标识
struct Identity {
string name;
string category;
};
通常category为空。只为name赋值。

⑶. 激活服务者
MyAdapter->add(servant, id);
将代表服务者的智能指针servant,以及标识id添加到适配器的服务者映射表(ASM)中,从而激活了服务者。可以接收客户端的服务了。客户端代理包含服务器寻址信息,请求的Ice对象标识id,客户调用操作时,对象标识一同发给服务器,服务器根据对象id查找ASM表,找到该标识的服务者,就把请求分派给它的成员函数。

MyAdapter->addWithUUID(servant);
未指定标识,使用UUID作为对象标识,也可以使用IceUtil::generateUUID()创建全局唯一标识,再赋给add操作。

⑷. 创建代理
NodePrx proxy = NodePrx::uncheckedCast(MyAdapter->add(servant, id));
现在,可以将proxy传给客户端使用了。

Ice提供了直接创建代理的操作:
Ice::Identity id;
id.name = IceUtil::generateUUID();
ObjectPrx o = MyAdapter->createProxy(id);
无论对象标识id对应的服务者是否被激活,该操作都会创建的代理。

分享到:
评论

相关推荐

    zeroc ice教程 ice环境配置 Ice中文教程 C++ ICE java ICE ICE入门 ice基础教程 ice开发文档

    从编程语言映射的角度看,文档深入讲解了Slice到C++和Java的映射机制。在C++映射章节中,文档涵盖了标识符映射、模块映射、简单内建类型映射、用户定义类型映射、接口映射、操作映射以及异常处理等。这些内容对开发...

    ICE框架 C++示例程序

    3. **接口定义语言(IDL)**:ICE使用称为“Slice”的接口定义语言来描述服务接口, Slice文件可以被编译成不同语言的客户端和服务器端代码。 4. **自动类型映射**:ICE支持基本数据类型和自定义类型的自动序列化和...

    ICE中间件教程

    **4.3 服务器端Slice到C++的映射** - **4.3.1 服务器端程序流程**:描述了服务器端程序的一般流程。 - **4.3.2 Ice::Application类**:服务器端程序的入口类。 - **4.3.3 Ice::Service类**:服务器端对象的基类。 -...

    zeroc ice微服务架构用户手册

    * 故障转移:Ice 服务允许客户端在服务器端故障时自动转移到其他服务器端。 Architectural Benefits of Ice Ice 架构模型提供了一些架构上的优点,包括: * 高性能:Ice 架构模型能够提供高性能的数据传输能力,...

    ice分布式应用开发

    - 类型映射:将Slice中的类型映射为相应的C++或Java类型。 - 接口映射:将Slice接口映射为C++类或Java接口。 - 方法映射:将Slice操作映射为类成员函数或接口方法。 - 异常映射:将Slice异常映射为C++或Java异常...

    ice分布式程序设计中文版

    书籍涵盖了ICE的核心概念、Slice语言的使用、以及如何将Slice定义转换为C++和Java代码。 书中第一部分着重于ICE的综述,包括ICE的基本架构、服务以及它与传统分布式对象计算模型CORBA的对比。作者提供了编写Hello...

    Zeroc ICE中间件slice2java的ant脚本(v1u0_0)

    ICE支持多种编程语言,包括C++、Java、Python等,使得跨平台的通信变得简单。在ICE中,`slice`是一种接口定义语言,类似于IDL(Interface Definition Language),用于描述服务接口和数据类型。`slice2java`是ICE...

    ICE分布式程序设计中文版

    第 10 章 服务器端的 Slice-to-C++ 映射 235 10.1 本章综 235 10.2 引言 235 10.3 服务器端 main函数 236 10.4 接口的映射 247 10.5 参数传递 249 10.6 引发异常 251 10.7 对象体现 252 10.8 总结 257 第 11 章开发 ...

    ICE中文编程指南

    #### 五、客户端的Slice到语言映射 - **C++映射**: - Slice定义被转换成C++代码,包括头文件和实现文件。 - 映射规则包括标识符、类型、异常等方面的转换。 - **Java映射**: - Slice定义同样被转换成Java代码...

    ZeroC Ice3.7 官方手册英文版加注中文书签

    - **语言映射概述(Overview of the Language Mappings)**:详细介绍了Ice支持的各种编程语言(如C++、Java等)与Slice之间的映射关系。 - **客户端和服务端结构(Client and Server Structure)**:描述了如何在...

    Ice-1.3.0-中文文档.pdf

    - 文档由几部分组成,包括引言、Ice综述、Ice核心概念、客户端的Slice-to-C++映射、客户端的Slice-to-Java映射等章节。 - 每章都包括了综述、内容细节以及总结。 5. Slice语言: - Slice是Interface Definition ...

    gulp-ice-builder:Gulp插件,可自动将Slice文件编译为JavaScript

    slice2js gulp-ice-builder调用slice2js编译器。 您可以使用以下命令安装最新的 : npm install slice2js --save-dev 用法 const iceBuilder = require ( 'gulp-ice-builder' ) ; gulp . task ( "slice2js" , ( ) ...

    ICE客户端与服务端通信Demo

    平台编译环境:VS2017 ICE版本:3.7.7 ICEbuilder:5.0.9 源码中有两套程序: Server:启动服务器,等待连接 。连接后可双方通信 Client:连接服务器,与服务器通讯。...Slice: 手写几个接口即可。

    Ice-3.4.0中文开发手册1

    在Slice语言章节之后,手册详细阐述了Slice到C++和Java的映射,这有助于开发者理解如何将Slice定义转换为实际的代码。对于C++,讲解了标识符、模块、类型、常量、异常、接口和操作的映射规则,以及异常处理和类的...

    用ICE开发分布式程序.txt

    Slice语言简洁且易于理解,它支持基本的数据类型、枚举、结构体、类等,并能自动生成对应的客户端和服务器端代码。 - **Slice示例**: 以下是一个简单的Slice定义示例: ```slice module Demo { interface ...

    Zeroc ICE中间件slice2java的ant脚本

    Ice支持多种编程语言,包括Java,C++,Python等,使得应用程序能够轻松地进行网络通信和数据交换。在分布式系统中,中间件起到桥梁的作用,简化了不同组件之间的通信。 “slice2java”是Ice工具集的一部分,用于将 ...

Global site tag (gtag.js) - Google Analytics