ACE_Service_Config 클래스는 서비스 환경을 설정할 때 사용되는 클래스입니다. 서비스를 등록하거나 서비스를 제거하거나, 일시 정지 및 재시작 등과 같은 기능을 가지고 있습니다.
하나의 서비스에서 특정 ACE_Reactor를 사용하도록 한다면, 서비스가 제거되면 같은 ACE_Reactor에 의존하는 이벤트 객체도 서비스가 종료되며 메모리에서 제거됩니다. 이러한 문제는 서비스를 올리고 내리는 기능을 가진 특별한 서비스에서는 문제가 발생할 수 있으며, 이러한 경우에는 서비스 생명 주기와 무관한 ACE_Reactor 객체에 의존하는 것이 좋습니다.
결국 서비스 객체가 죽으면 해당 서비스 객체가 만든 부산물까지 살아져야 한다면 ACE_Reactor를 서비스 객체의 멤버로 설정하면 된다. 만약 서비스 객체와 해당 서비스 객체가 무관하게 운영될 필요가 있다면, 서비스 객체와 생명 주기가 다른 ACE_Reactor 객체를 사용하도록 해야 한다.
Commander 서비스 코딩 부분
ES.h 파일
#pragma once
#include <ace/Service_Object.h>
#include "GAcceptor.h"
class ES:public ACE_Service_Object
{
private:
GAcceptor* obj_;
public:
ES(void);
~ES(void);
private:
// Shared_Object Interface
virtual int init (int argc, ACE_TCHAR *argv[]);
virtual int fini (void);
// Service_Object Interface
virtual int suspend (void);
virtual int resume (void);
};
ES.cpp 파일
#include "ES.h"
#include <ace/Get_Opt.h>
#include <iostream>
#include <ace/Reactor.h>
#define MY_SERVICE_Export __declspec(dllexport)
ACE_FACTORY_DEFINE( MY_SERVICE, ES);
ES::ES(void)
:obj_(NULL)
{
this->reactor( ACE_Reactor::instance() );
}
ES::~ES(void)
{
}
// -a 192.168.0.2:5000
int
ES::init (int argc, ACE_TCHAR *argv[]){
char* p = "127.0.0.1:5000";
ACE_Get_Opt opt( argc, argv, "a:",0);
for( int c; -1 != (c = opt()); ){
if( 'a' == c){
p = opt.opt_arg();
}
}
std::cout<<std::endl<<"Commander::init"<<std::endl;
obj_ = new GAcceptor(p ,this->reactor());
return 0;
}
int
ES::suspend (void){
std::cout<<std::endl<<"Commander::suspend"<<std::endl;
this->reactor()->suspend_handler( obj_);
return 0;
}
int
ES::resume (void){
std::cout<<std::endl<<"Commander::resume"<<std::endl;
this->reactor()->resume_handler( obj_);
return 0;
}
int
ES::fini (void){
obj_->handle_close( ACE_INVALID_HANDLE, 0);
std::cout<<std::endl<<"Commander::fini"<<std::endl;
return 0;
}
EchoService.h 파일
#pragma once
#include <ace/Event_Handler.h>
#include <ace/Reactor.h>
#include <ace/SOCK_Acceptor.h>
#include <ace/SOCK_Stream.h>
#include <ace/INET_Addr.h>
#include <ace/Message_Block.h>
class EchoService:public ACE_Event_Handler
{
private:
ACE_SOCK_Stream peer_;
ACE_INET_Addr addr_;
ACE_Message_Block msg_;
public:
EchoService(ACE_SOCK_Acceptor& acceptor, ACE_Reactor* reactor);
~EchoService(void);
virtual ACE_HANDLE get_handle (void) const;
virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
virtual int handle_close (ACE_HANDLE handle,ACE_Reactor_Mask close_mask);
};
EchoService.cpp 파일
#include "EchoService.h"
#include <iostream>
#include <ace/OS.h>
#include <ace/Service_Config.h>
#define MAX_COMMAND 1024
EchoService::EchoService(ACE_SOCK_Acceptor& acceptor, ACE_Reactor* reactor)
:ACE_Event_Handler(reactor),peer_(ACE_INVALID_HANDLE),msg_(MAX_COMMAND)
{
if( -1 == acceptor.accept(peer_,&addr_) ){
delete this;
return;
}
char addr_string[256];
addr_.addr_to_string(addr_string, 256);
std::cout<<std::endl<<"Enter Client:"<<addr_string<<std::endl;
this->reactor()->register_handler( this,ACE_Event_Handler::READ_MASK);
}
EchoService::~EchoService(void)
{
}
ACE_HANDLE
EchoService::get_handle (void) const{
return this->peer_.get_handle();
}
int
EchoService::handle_input (ACE_HANDLE fd/* = ACE_INVALID_HANDLE*/){
const int BUF =1024;
unsigned char in[BUF];
ACE_Time_Value vt(0,0);
ssize_t len =this->peer_.recv(in, BUF,&vt);
if( len <= 0){//클라이언트 종료. 통신 에러
return -1;
}
if( ( msg_.length() + len) >MAX_COMMAND ){
return -1;
}
if( '\n'== in[len-1] || '\r'== in[len-1] ){
in[len-1] = 0;
}
ACE_OS::memcpy( msg_.wr_ptr(), in, len);
msg_.wr_ptr( len );
if( 0 == in[len-1]){
std::cout<<std::endl<<"User Command:"<<msg_.rd_ptr() << std::endl;
ACE_Service_Config::process_directive( msg_.rd_ptr());
msg_.length(0);
msg_.crunch();
}
return 0;
}
int
EchoService::handle_close (ACE_HANDLE handle,ACE_Reactor_Mask close_mask){
char addr_string[256];
addr_.addr_to_string(addr_string, 256);
std::cout<<std::endl<<"Exit Client:"<<addr_string<<std::endl;
ACE_Reactor_Mask m = ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL;
this->reactor()->remove_handler(this,m);
this->peer_.close();
delete this;
return 0;
}
GAcceptor.h 파일
#pragma once
#include <ace/Event_Handler.h>
#include <ace/Reactor.h>
#include <ace/SOCK_Acceptor.h>
class GAcceptor:public ACE_Event_Handler
{
private:
ACE_SOCK_Acceptor acceptor_;
public:
GAcceptor(const char* ipstr,ACE_Reactor* reactor);
~GAcceptor(void);
virtual ACE_HANDLE get_handle (void) const;
virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
virtual int handle_close (ACE_HANDLE handle,ACE_Reactor_Mask close_mask);
};
GAcceptor.cpp 파일
#include "GAcceptor.h"
#include <ace/INET_Addr.h>
#include <iostream>
#include "EchoService.h"
GAcceptor::GAcceptor(const char* ipstr,ACE_Reactor* reactor)
:ACE_Event_Handler(reactor)
{
ACE_INET_Addr addr(ipstr);
int bret = acceptor_.open(addr,1);
if( -1==bret){
std::cout<<std::endl<<"Listen fail:"<<ipstr<<std::endl;
delete this;
return;
}
std::cout<<std::endl<<"Server start:"<<ipstr<<std::endl;
this->reactor()->register_handler( this, ACE_Event_Handler::ACCEPT_MASK);
}
GAcceptor::~GAcceptor(void)
{
}
ACE_HANDLE
GAcceptor::get_handle (void) const{
return this->acceptor_.get_handle();
}
int
GAcceptor::handle_input (ACE_HANDLE fd/* = ACE_INVALID_HANDLE*/){
new EchoService(this->acceptor_,this->reactor());
return 0;
}
int
GAcceptor::handle_close (ACE_HANDLE handle,ACE_Reactor_Mask close_mask){
ACE_Reactor_Mask m = ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL;
this->reactor()->remove_handler( this, m);
this->acceptor_.close();
delete this;
return 0;
}
svc.conf 파일
dynamic EchoService1 Service_Object * EchoService:_make_ES() "-a 192.168.0.2:1500"
dynamic EchoService2 Service_Object * EchoService:_make_ES() "-a 192.168.0.2:2500"
dynamic Commander Service_Object * Commander:_make_ES() "-a 192.168.0.2:1000"