ACE Acceptor-Connector framework는 Acceptor-Connector 패턴의 구현체입니다. 서버, 또는 클라이언트의 접속 처리는 매번 반복됨으로 별도의 프레임웍으로 개발한다. 따라서 프로그래머는 실제 서비스를 설계하는 과정에만 집중할 수 있다.
서비스 객체와 접속 처리 객체와의 커플링은 최소하고, 응집력은 강화하기 위해, 템플릿으로 연결함으로써 최종적으로 서비스 객체를 서버로 사용할지, 클라이언트로 사용할지, 프로그래머가 결정할 수 있도록 합니다.
ACE_Svc_Handler는 open 함수에서 별도의 쓰레드를 생성하지 않습니다. 대신 reactor에 READ_MASK를 등록합니다.
close 함수는 handle_close를, handle_close는 destroy를 호출하고, 최종적으로 delete this가 호출됩니다. 타이머와 등록된 마스크 정보를 제거하고 소켓을 닫는 일련의 과정이 shutdown 함수에서 진행됩니다.
ACE_Svc_Handler는 open 함수가 호출되는 시점은 스트리밍 객체가 생성된 이후입니다. close 함수가 호출되는 시점은 접속에 실패한 경우입니다.
EchoService.h
#pragma once
#include <ace/Svc_Handler.h>
#include <ace/SOCK_Stream.h>
#include <ace/Synch.h>
class EchoService:public ACE_Svc_Handler<ACE_SOCK_Stream, ACE_NULL_SYNCH>
{
private:
typedef ACE_Svc_Handler<ACE_SOCK_Stream, ACE_NULL_SYNCH> PARENT;
public:
EchoService(void);
~EchoService(void);
virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
virtual int open (void * = 0);
};
EchoService.cpp
#include "EchoService.h"
#include <iostream>
EchoService::EchoService(void)
{
}
EchoService::~EchoService(void)
{
}
int
EchoService::handle_input (ACE_HANDLE fd/* = ACE_INVALID_HANDLE*/){
char buf[1024];
ssize_t len = this->peer().recv( buf, 1024);
if(len<=0){
std::cout<<std::endl<<" Client Exit:";
return -1;
}
buf[len]=0;
std::cout<<std::endl<< buf;
this->peer().send( buf, len);
return 0;
}
int
EchoService::open (void * data/* = 0*/){
std::cout<<std::endl<<" Client Enter:";
return PARENT::open(data);
}
EchoServer2.cpp
// EchoServer2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <ace/ACE.h>
#include "EchoService.h"
#include <ace/Acceptor.h>
#include <ace/SOCK_Acceptor.h>
int _tmain(int argc, _TCHAR* argv[])
{
ACE::init();
{
typedef ACE_Acceptor<EchoService,ACE_SOCK_Acceptor> ECHO_SERVER;
ECHO_SERVER m;
ACE_SOCK_Acceptor::PEER_ADDR addr("192.168.0.2:1000");
m.open(addr);
ACE_Reactor::instance()->run_reactor_event_loop();
}
ACE::fini();
return 0;
}