Ice笔记-利用Ice::Service类简化Ice应用

Ice笔记-利用Ice::Service类简化Ice应用

Ice笔记-利用Application类简化Ice应用

 
一.概要

一般而言,Ice::Application 类对Ice 和服器来已经非常方便但在有些情况下,用可能需要作Unix 看守(daemon)或Win32 运行在系这样的情况,Ice 提供了Ice::Service 一个可与Ice::Application 相比的,但它封装了低的、 针对特定平台的初始化和关——系常常需要使用这样的步

 
Ice::Application的异同
1. Ice::ApplicationIce::Service的功能类似,抽象出模型也相近。
但Ice::Service的含义是让一个应用用比Ice::Application更好的管理形式 ――“服务”的方式运行。
不会、也不需要在
Ice::Application中包含多个Ice::Service
 
2. Ice::Service
的需用户继承的核心函数为start()Ice::Application需用户继承的核心函数为run(),不能混淆, 因为Ice::Service也有一个run()函数
 
3. Ice ::Service
隐含了对Service的结束通过run()中调用waitForShutdown()),无需用户显式使用类似ic->waitForShutdown()Ice::Application必须主动在其run()函数中显式等待。可以说,Ice::ServiceIce::Application提供了更贴心的服务,但换个角度来说,Ice::Application更何尝不是给用户提供了更好灵活性和简洁性。

4. Ice::Application对信号的支持要好于Ice::Service。双方都能过滤SIGHUP信号。

就代码而言,感觉是这两个类不是同一个人写的。因为这两个类之间可互相补充的东西不少,甚至可以合并为同一个类。不知到ZeroC是基于何种考虑?

 
类成员

下面是Ice::Service 的定为方便起见将所有的虚函数都并列在一起。

class  ICE_API Service
{
public :
    Service();
    
virtual   ~ Service();

    
//  关闭服务,默认操作是关闭服务所使用的Ice通信器
    
//  如果你需要其它的附加操作,继承并改写此函数
     virtual   bool  shutdown();

    
//  信号回调函数,表示Service被信号所中断,默认操作是调用shutdown()函数
     virtual   void  interrupt();

    
//  供给IceUtil::CtrlHandler注册的原始信号处理函数
    
//  它处理完SIGHUP后调用interrupt。一般无需继承和改写,除非你想自己处理SIGHUP
     virtual   void  handleInterrupt( int );

protected :
    
//  允许子类执行它的启动活动,比如扫描所提供的参数向量、识别命令行选项,创建对象 //  适配器,以及注册servants。
    // 如果启动成功,子类必须返回true,否则返回false。
    
//  一般必须继承,并在其中实现应用自己的应用逻辑。
     virtual   bool  start( int char * [])  =   0 ;

    
//  阻塞等待Service的关闭。缺省操作是调用Ice通信器的waitForShutdown()。
     virtual   void  waitForShutdown();

    
//  服务停止清理函数。决定了main()的返回值,缺省操作返回true。
    
//  如果你有其它资源需要清理,需要继承并改写该函数。
     virtual   bool  stop();

    
//  初始化Service所用的Ice通信器
    
//  Service类提供了一个方法让用户决定Ice通信器的构造方式
     virtual  Ice::CommunicatorPtr initializeCommunicator( int & char * [],  const  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 & );
    
virtual   void  print( const  std:: string & );

public :
    
    
//  服务入口函数,处理服务安装、卸载和run()的调用
     int  main( int & char * [],  const  InitializationData &   =  InitializationData());
    
int  main(StringSeq & const  InitializationData &   =  InitializationData());
    
//
    
//  返回服务使用的Ice通信器
    Ice::CommunicatorPtr communicator()  const ;
    
//
    
//  返回服务的惟一实例,注意实例是静态提供的。
     static  Service *  instance();
    
//
    
//  判断当前运行模式。如果是以Win32服务或linux daemon方式运行,返回true.
    
//  否则返回false
     bool  service()  const ;

    
//  返回当前Service名字,等同于Ice::Application::appName()
    std:: string  name()  const ;

    
//  检查当前平台是否支持后台运行(win32服务/linux daemon)
     bool  checkSystem()  const ;

    
//  Service的真正执行函数    
     int  run( int & char * [],  const  InitializationData &   =  InitializationData());

protected :
    
//  允许信号中断
     void  enableInterrupt();
    
//  禁止信号中断
     void  disableInterrupt();

private :

    Ice::LoggerPtr _logger;    
//  Service使用的Log对象
    Ice::CommunicatorPtr _communicator;  //  Services使用的通信器
     bool  _nohup;         //  是否忽略SIGHUP函数
     bool  _service;         //  Service运行模式是否为服务/daemon
    std:: string  _name;     //   Service应用名
  
    
static  Service *  _instance;  //  Service的惟一静态实例
};

四.用法举例

虽然Ice::Service可改写的行为较多,但一般情况下,只需改写:start(), stop()interrupt()。继承interrupt(), 要么注意调用父类的interrupt()函数,否则自己处
理信号。

 

class  MyService :  public  Ice::Service 
{
protected :
    
virtual   bool  start( int char   *  []);
    
virtual   bool  stop();
    
virtual   void  interrupt();
private :
    Ice::ObjectAdapterPtr m_adapter;
};

void  MyService::interrupt()
{
    std::cout 
<<   " Receive signal ... "   <<  std::endl;
    Ice::Service::interrupt();
}
bool  MyService::stop()
{
    std::cout 
<<   " Stop running ... "   <<  std::endl;
    
return   true ;
}
bool  MyService::start( int  argc,  char   *  argv[])
{
    std::
string  endpoint  =   " tcp -p 10000:udp -p 10000 " ;
    m_adapter 
=  communicator() -> createObjectAdapterWithEndpoints( " MonitorAdapter " , endpoint);

    Ice::ObjectPtr 
object   =   new  CCheckFile;
    m_adapter
-> add( object ,communicator() -> stringToIdentity( " CheckFile " ));
    m_adapter
-> activate();
    
return   true ;
}

int  main( int  argc,  char *  argv[])
{
    MyService svc;
    
int  ret  =  svc.main(argc, argv);
    
return  ret;
}

五.作为后台服务/daemon运行

Ice::Service提供的安装方式很简洁,这个功能也是Ice::Service的主要魅力所在。

  1) Unix 看守

Unix 平台上, Ice::Service 识别以下命令行选项

--daemon

指明程序 应该 看守运行。 涉及到 建一个后台子 程, Service::main 将在 个子 程中 行其任 。在子 程成功 start 函数之前,父 程不会 ( shell 脚本启动看守常常会带来不确定性,上述行为消除了这一不确定性,因为它确保了命令调用不会在看守准备好接收请求之前就完成 ) 。除非另外收到指示,否 Ice::Service 会把子 程的当前工作目 录变 根目 ,并关 所有无用的文件描述符。注意, 在通信器初始化之前,各文件描述符不会关 ,也就是 ,在 时间 里, 入、 出,以及 错误 都可以使用。 例如, IceSSL 插件可能需要在 入上 提示 入口令,而如果 置了 Ice.PrintProcessId Ice 可能要在 出上打印子 id

--noclose

阻止 Ice::Service 无用的文件描述符。 调试 程中, 可能会很有用,因 这样 一来,你就可以通 看守的 出和 错误进 出了。

--nochdir

阻止 Ice::Service 更当前工作目 --noclose --nochdir 选项 只能和 --daemon 一起指定。在 传给 start 函数的参数向量中, 选项 会被移除。

2) Win32 服务

Win32 平台上2,如果指定了--service选项Ice::Service 会把用作Windows (Windows 95/98/ME 上不支持Windows 服务)

--service NAME

名叫 NAME Windows 传给 start 函数的参数向量中, 选项 会被移除。
但是,在 用作 Windows 运行之前,它必 先被安装,因此 Ice::Service 类还 支持另外一些的命令行 选项 ,用于 行管理活

--install NAME [--display DISP] [--executable EXEC][ARG ...]
安装NAME 如果指定了--display 选项,就把DISP 用作服示名,否就使用NAME。如果指定了--executable 选项,就把EXEC 用作服的可行路径名,否就使用可行文件的路径名来--install其他任何参数都会不加改传给Service::start 函数。注意,在启动时传给的参数集中,个命令会自增加命令行参数--service NAME,因此,你不需要式地指定选项

--uninstall NAME
移除NAME 如果服目前是活的,在反安装之前,必先使它停止。

--start NAME [ARG ...]
NAME 。其他任何参数都会不加改传给Service::start 函数。    

--stop NAME
停止NAME 。如果指定的管理命令不止一个,或者在使用--service 的同时还使用了管理命令 ,就会错误。在行了管理命令之后,程序会立即止。Ice::Service 支持Windows 控制代SERVICE_CONTROL_INTERROGATE SERVICE_CONTROL_STOP。在收到SERVICE_CONTROL_STOP ,Ice::Service shutdown 函数。
 

六.代码分析

分析run函数和信号处理函数handleInterrupt

1. run函数

int  Ice::Service::run( int &  argc,  char *  argv[],  const  InitializationData &  initData)
{
    
//  run()被main()函数调用,在main()函数中解析用户参数并决定运行模式
    
//  决定在后台运行
     if (_service)
    {
#ifdef _WIN32
        
return  runService(argc, argv, initData);
#else
        
return  runDaemon(argc, argv, initData);
#endif
    }

    
//  在前台运行
     int  status  =  EXIT_FAILURE;
    
try
    {
        
//  设置信号捕捉器,其作用实现在对Application的分析文章中描述
        _ctrlCHandler  =   new  IceUtil::CtrlCHandler;

        
//
        
//  初始化Ice通信器, 注意这里你可以通过改写initializeCommunicator()
        
//  来控制Ice通信器的生成
        _communicator  =  initializeCommunicator(argc, argv, initData);

        
//  有关log的设定
        _logger  =  _communicator -> getLogger();

        
//  从配置读取Ice.Nohup,默认值为1。决定是否要忽略SIGHUP消息.
//  使得应用在用户注销或者shell退出后依然运行
        _nohup  =  _communicator -> getProperties() -> getPropertyAsIntWithDefault( " Ice.Nohup " 1 >   0 ;

        
//  执行用户的主体函数
         if (start(argc, argv))
        {
            
//  等待应用结束,注意Ice::Application不会等待结束。
            waitForShutdown();

            
//  调用用户的清理函数
             if (stop())
            {
                status 
=  EXIT_SUCCESS;
            }
        }
    }
    
catch ( const  IceUtil::Exception &  ex)
    {
        ostringstream ostr;
        ostr 
<<   " service caught unhandled Ice exception: "   <<  ex;
        error(ostr.str());
    }
    
catch ( const  std::exception &  ex)
    {
        ostringstream ostr;
        ostr 
<<   " service caught unhandled std::exception: "   <<  ex.what();
        error(ostr.str());
    }
    
catch ( const  std:: string &  msg)
    {
        ostringstream ostr;
        ostr 
<<   " service caught unhandled exception: "   <<  msg;
        error(ostr.str());
    }
    
catch ( const   char *  msg)
    {
        ostringstream ostr;
        ostr 
<<   " service caught unhandled exception: "   <<  msg;
        error(ostr.str());
    }
    
catch (...)
    {
        error(
" service caught unhandled C++ exception " );
    }

    
try
    {
        _communicator
-> destroy();
    }
    
catch (...)
    {
    }

    
return  status;
}

  2. handleInterrupt()函数

void  Ice::Service::handleInterrupt( int  sig)
{
#ifdef _WIN32
    
//  如果设置了Ice.Nohup,则忽略用户注销消息
     if (_nohup  &&  sig  ==  CTRL_LOGOFF_EVENT)
    {
        
return ;
    }
#else
    
//  如果设置了Ice.Nohup,则忽略shell退出/用户注销消息
     if (_nohup  &&  sig  ==  SIGHUP)
    {
        
return ;
    }
#endif
    
//  调用信号回调函数
    interrupt();
}

注意,interrupt()的默认实现是调用shutdown(),也就是关闭Service。因此默认情况下,Ctrl+C就可以正常退出。

七.参考文献
Ice- 1.3.0 中文手册(马维达,感谢他的无私贡献)
Ice- 3.1.1 英文手册
Ice- 3.2.1 源码

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值