1. 개요
클라이언트로 서비스를 제공하는 Server 인터페이스 클래스.
클라이언트로부터 요청을 처리하는 일반적인 서비스를 정의하는 인터페이스 클래스입니다. Acceptor와 Executor의 구현제를 소유하며, 서비스 처리에 대한 각종 통계정보를 수집합니다.
Server 클래스는 최소한의 작업을 통해 application-specific하게 재정의 될수 있어야 합니다. application-specific하도록 서버를 재구성하기 위해서는 Request_Handler를 상속하는 새로운 Request_Handler를 정의해야하며, 추상 클래스인 Server에서는 미래에 특정 목적을 가지고 작성될 새로운 Request_Handler를 알수 없기때문에, Server를 상속하는 새로운 서비스 객체에서 make_request_handler를 재정의해야 합니다.
새로운 서비스를 정의하기 위해 필요한 작업은 위에서 설명한 내용이 전부입니다!
신규 클라이언트에 대한 처리와, 네트워크 입출력에 대한 복잡한 처리를 고민할 필요가 없습니다. Server 클래스는 Windows에서 폭넓게 적용될수 있는 IOCP를 기반으로한 Proactor구현체를 포함하며, 클라이언트의 Session관리 및 I/O 연산을 자동화 합니다.
따라서, 고성능의 서버를 제작하기 위해 Socket을 사용한 Low한 프로그래밍 작업에서 벗어나, 상위 계층에서 보다 생산적인 일에 집중할 수 있습니다.
2. Server의 선언은 다음과 같습니다.
// -*- C++ -*-
//=============================================================================
/**
* @file server.h
*
* $Id: server.h Fri Mon 16 17:23:23 GMT+09:00 2009
*
* @author Copyright 2008-2009 SOPT(Shout Our Passion Together)
*/
//=============================================================================
#ifndef _SERVER_DEFINE
#define _SERVER_DEFINE
#if !defined (ACE_LACKS_PRAGMA_ONCE)
#pragma once
#endif
#include "ace/Task.h"
#include "ace/Auto_Ptr.h"
#include "ace/INET_Addr.h"
#include "ace/Message_Block.h"
#include "ace/Atomic_Op.h"
#include "ace/Singleton.h"
#include "acceptor.h"
#include "executor.h"
#include "stream_handler.h"
#include "request_handler.h"
#include "config.h"
#include "logmgr.h"
#include <list>
#if defined(ACE_WIN32)
#include "sopt_export.h"
#elif
typedef SOPT_Export ACE_Export
#endif
class ACE_Proactor;
static int disable_signal(int sigmin, int sigmax);
namespace libsopt {
/**
* @class Server
*
* @brief 클라이언트로 서비스를 제공하는 Server 인터페이스 클래스.
*
* 클라이언트로부터 요청을 처리하는 일반적인 서비스를 정의하는 인터페이스 클래스입니다.
* Acceptor와 Executor의 구현제를 소유하며, 서비스 처리에 대한 각종 통계정보를 수집합니다.
*
* Server 클래스는 최소한의 작업을 통해 application-specific하게 재정의 될수 있어야 합니다.
* application-specific하도록 서버를 재구성하기 위해서는 Request_Handler를 상속하는
* 새로운 Request_Handler를 정의해야하며, 추상 클래스인 Server에서는 미래에 특정 목적을 가지고 작성될
* 새로운 Request_Handler를 알수 없기때문에, Server를 상속하는 새로운 서비스 객체에서
* make_request_handler를 재정의해야 합니다.
*
* 새로운 서비스를 정의하기 위해 필요한 작업은 위에서 설명한 내용이 전부입니다!
*
* 신규 클라이언트에 대한 처리와, 네트워크 입출력에 대한 복잡한 처리를 고민할 필요가 없습니다.
* Server 클래스는 Windows에서 폭넓게 적용될수 있는 IOCP를 기반으로한 Proactor구현체를 포함하며,
* 클라이언트의 Session관리 및 I/O 연산을 자동화 합니다.
*
* 따라서, 고성능의 서버를 제작하기 위해 Socket을 사용한 Low한 프로그래밍 작업에서 벗어나,
* 상위 계층에서 보다 생산적인 일에 집중할 수 있습니다.
*/
class SOPT_Export Server :
public ACE_Task_Base {
private :
volatile int server_state_;
ACE_INET_Addr listen_;
ACE_Proactor *proactor_;
ACE_Thread_Mutex guard_;
ACE_Auto_Ptr<Acceptor> acceptor_;
ACE_Auto_Ptr<Executor> executor_;
ACE_Atomic_Op<ACE_Thread_Mutex, size_t> client_count_, accept_count_;
ACE_Atomic_Op<ACE_Thread_Mutex, size_t> total_request_count_, total_response_count_;
ACE_Atomic_Op<ACE_Thread_Mutex, size_t> total_byte_to_recv_, total_byte_to_send_;
typedef std::list<Stream_Handler *> STREAM_HANDLER_LIST;
typedef STREAM_HANDLER_LIST::iterator STREAM_HANDLER_LIST_ITER;
STREAM_HANDLER_LIST stream_handler_list_;
/**
* Proactor I/O 디스패치 쓰레드.
* Config 클래스의 PROACTOR_DISPATH_THREAD_COUNT필드값을 참조합니다.
*/
virtual int svc();
/**
* Server에 연결되어있는 모든 클라이언트와 연결을 종료하고,
* 리소스를 해제합니다
*/
void close_and_clear_all_stream_handler();
/**
* 로그파일을 저장할 경로의 디렉토리를 생성합니다.
*/
void mklogdir(const char *path);
protected :
ACE_Auto_Ptr<LogMgr> logger_;
ACE_Auto_Ptr<Config> config_;
/**
* Acceptor 객체를 생성합니다.
*
* @retval Acceptor * Acceptor 객체 포인터
*/
virtual Acceptor * make_acceptor();
/**
* Executor 객체를 생성합니다.
*
* @retval Executor * Executor 객체 포인터
*/
virtual Executor * make_executor();
/**
* Proactor 객체를 생성합니다.
*
* @retval ACE_Proactor * ACE_Proactor 객체 포인터
*/
virtual ACE_Proactor * make_proactor();
public :
/// Serve Controller 클래스.
class Controller;
friend class Controller;
/**
* @enum SERVER_STATE
*
* @brief Executor의 타입
*/
enum SERVER_STATE { STARTING = 0x01, RUNNING, STOPPING, STOPPED };
/**
* 생성자
*
* @param *logger LogMgr 객체 포인터
* @param *config Config 객체 포인터
*/
Server(LogMgr *logger, Config *config)
: server_state_(STOPPED),
proactor_(0), acceptor_(0), executor_(0), client_count_(0), accept_count_(0),
logger_(logger), config_(config)
{ /* empty */ }
/// 기본소멸자
virtual ~Server()
{ /* empty */ }
/// 서비스를 시작합니다.
int run_server_process();
/// 서비스를 종료합니다.
int end_server_process();
/**
* Server의 실행상태를 확인합니다.
*
* @param state 확인할 상태
*
* @retval 1 Server는 state 상태에 있습니다.
* @retval 0 Server는 state 상태에 있지 않습니다.
*/
int check_server_state(SERVER_STATE state) const;
/**
* Server의 실행상태를 변경합니다.
*
* @param to_ch_state 변경할 상태
*/
void change_server_state(SERVER_STATE to_ch_state);
/**
* 클라이언트의 연결완료 이벤트 통지 메소드
*
* @param to_ch_state *h 신규 서비스 핸들러 객체 포인터
*/
virtual void on_connection_established(Stream_Handler *h);
/**
* 클라이언트의 연결종료 이벤트 통지 메소드
*
* @param to_ch_state *h 연결을 종료할 서비스 핸들러 객체 포인터
*/
virtual void on_connection_closed(Stream_Handler *h);
/**
* Acceotor의 make_handler 메소드를 통해 호출됩니다.
* 기본구현은 ::operator new를 사용해 객체를 생성합니다.
* 별도의 Allocator/Deallocator를 구현하여 사용할수 있습니다.
*
* @retval Stream_Handler * 신규 서비스 핸들러 객체 포인터
*/
virtual Stream_Handler * make_stream_handler();
/**
* make_stream_handler를 통해 생성된 객체를 해제합니다.
* 기본구현은 ::operator delete를 사용해 객체를 소멸시킵니다.
* 별도의 Allocator/Deallocator를 구현하여 사용할수 있습니다.
*
* @param Stream_Handler * 리소스를 해제할 서비스 핸들러 객체 포인터
*/
virtual void release_stream_handler(Stream_Handler *h);
/**
* Request_Hadler 객체를 생성합니다.
* 기본구현은 ::operator new를 사용해 객체를 생성합니다.
* 별도의 Allocator/Deallocator를 구현하여 사용할수 있습니다.
* Server를 상속하는 클래스는 반드시 메소드를 구현해야 합니다.
*
* @retval Request_Handler * Request_Hadler 객체 포인터
*/
virtual Request_Handler * make_request_handler() = 0;
/**
* make_request_handler통해 생성된 객체를 해제합니다.
* 기본구현은 ::operator delete를 사용해 객체를 소멸시킵니다.
* 별도의 Allocator/Deallocator를 구현하여 사용할수 있습니다.
* Server를 상속하는 클래스는 반드시 메소드를 구현해야 합니다.
*
* @param Request_Handler * 리소스를 해제할 Request_Handler 객체 포인터
*/
virtual void release_request_handler(Request_Handler *r) = 0;
/**
* Request_Handler에 정의된 Header와 Payload가 정상적으로 수신되었을때,
* 호출되는 이벤트 통지 메소드.
* 수신된 Request_Handler가 urgent_request라면 즉시 처리되며,
* 그렇지 않다면면 Executor로 전달됩니다.
* Executor로는 Stream_Handler 객체 포인터와 Request_Handler 객체 포인터 모두
* 전달되며, 특히 Stream_Handler 객체는 RefCount가 1증가합니다.
*
* @param Stream_Handler * Request_Handler를 수신한 서비스 핸들러 객체 포인터
* @param Request_Handler * 수신된 Request_Handler 객체 포인터
*/
virtual void stream_read_complete(Stream_Handler *h, Request_Handler *r);
/**
* 클라이언트로 데이터 전송이 완료되었을때 호출되는 이벤트 통지 메소드
*
* @param Stream_Handler * 데이터를 전송한 서비스 핸들러 객체 포인터
* @param Request_Handler * 전송이 완료된 Request_Handler 객체 포인터
*/
virtual void stream_write_complete(Stream_Handler *h, Request_Handler *r);
size_t current_client_count() const
{ return client_count_.value(); }
void increse_current_client_count()
{ ++client_count_; }
void decrese_current_client_count()
{ if( client_count_ > 0 ) --client_count_; }
void increse_accept_count()
{ ++accept_count_; }
size_t total_request_count() const
{ return total_request_count_.value(); }
void increse_total_request_count()
{ ++total_request_count_; }
size_t total_response_count() const
{ return total_response_count_.value(); }
void increse_total_response_count()
{ ++total_response_count_; }
size_t total_byte_to_recv() const
{ return total_byte_to_recv_.value(); }
void increse_total_byte_to_recv(size_t byte_to_recv)
{ total_byte_to_recv_ += byte_to_recv; }
size_t total_byte_to_send() const
{ return total_byte_to_send_.value(); }
void increse_total_byte_to_send(size_t byte_to_send)
{ total_byte_to_send_ += byte_to_send; }
Config * config() const
{ return config_.get(); }
};
/**
* @class Server::Controller
*
* @brief Server를 제어하는 Controller 클래스.
*
* 로컬 또는 원격지의 서버를 제어하기 위한 Controller 인터페이스 입니다.
* Controller의 기본구현은 콘솔입력을 받아들이며, 서버를 제어합니다.
* 콘솔에 exit를 입력해 Server를 종료시킬수 있습니다.
*/
class SOPT_Export Server::Controller :
public ACE_Task_Base {
protected :
/// Controller가 제어할 Server 객체 포인터
Server *serv_;
/**
* Controller의 상세구현을 포함하는 메소드이며, Active Object 패턴을 통해 실행됩니다.
* 기본 구현은 Config 객체의 LOGGING_LEVEL필드와 LOGGING_OUTPUT_TYPE필드를 이용하여,
* LogMgr의 초기화하며, 이후 콘솔입력을 처리합니다.
*
* 원격지를 통한 Server 제어를 위해서는 Server::Controller를 상속하는 application-specific한
* Controller를 이용할수 있습니다.
*
* 해당 메소드가 return되면, Controller와 Server는 순차적으로 종료합니다.
*/
virtual int svc();
public :
/// 기본생성자
explicit Controller(Server *serv)
: serv_(serv)
{ /* empty */ }
/// Controller를 시작합니다.
int run_server_controller_process()
{ return this->activate(); }
};
};
#endif
'포트폴리오 > libSOPT' 카테고리의 다른 글
| libSOPT다운로드 (0) | 2010/03/24 |
|---|---|
| libSOPT기반 echo server (0) | 2010/03/24 |
| libSOPT::Server (0) | 2010/03/24 |
| libSOPT::Executor (0) | 2010/03/24 |
| libSOPT::Request_Handler (0) | 2010/03/24 |
| libSOPT::Stream_Handler (0) | 2010/03/24 |
| libSOPT::Acceptor (0) | 2010/03/24 |
| libSOPT 소개 (0) | 2010/03/24 |
