用ACE靜態服務配置實現簡單的Echo服務
Stone Jiang (HuiHoo
ace)
本例完善了AGP中的示例
用ACE寫靜態服務配置與寫動態服務配置一樣簡單.本例實際了一個簡單的Echo服務.還包含了如何從ini文件中讀取服務配置
ACE靜態服務配置演示
? 示例說明
??? 完善了AGP中19章的例子
??? 演示了如何用ACE實現靜態服務配置
? 項目文件
??? HA_Status.h/cpp 服務接口程序
??? ClientHandler.h/cpp 事件處理器
??? svc_conf.static???? 靜態服務配置文件
??? status.ini?????????
????? 服務配置文件,服務偵聽的端口放在這里面的
? 調試命令行參數
??? -f svc_conf.static -d
詳細實現代碼
main.cpp
//@file:?main.cpp
//???????靜態服務配置主函數
//@author:?StoneJiang<2005119@gmail.com>
//@version:?0.1.0

#include?"ace/os.h"
#include?"ace/Log_Msg.h"
#include?"ace/Service_Config.h"
#include?"ace/Reactor.h"

int?ACE_TMAIN(int?argc,?ACE_TCHAR*?argv[])


{
??ACE_DEBUG((LM_DEBUG,ACE_TEXT("啟動主函數\n")));
??ACE_STATIC_SVC_REGISTER?(HA_Status_Descriptor);
??ACE_Service_Config::open?(argc,
????argv,
????ACE_DEFAULT_LOGGER_KEY,
????0);
??ACE_Reactor::instance?()->run_reactor_event_loop?();
??return?0;
}

HA_Status.h
//@file:?HA_Status.h
//???????服務接口類
#ifndef?HA_STATUS_H
#define?HA_STATUS_H
#include?"ace/Service_Object.h"
#include?"ace/INET_Addr.h"
#include?"ace/Acceptor.h"
#include?"ace/SOCK_Acceptor.h"
#include?"ClientHandler.h"

class?HA_Status?:public?ACE_Service_Object


{
public:
??virtual?int?init?(int?argc,?ACE_TCHAR?*argv[]);
??virtual?int?fini?(void);
??virtual?int?info?(ACE_TCHAR?**str,?size_t?len)?const;

private:
??ACE_Acceptor<ClientHandler,?ACE_SOCK_ACCEPTOR>?acceptor_;
??ACE_INET_Addr?listen_addr_;

};
#endifHA_Status.cpp
?
//@file:?HA_Status.cpp
//???????服務接口類的實現
#include?"HA_Status.h"
#include?"ace/service_config.h"
#include?"ace/OS_NS_stdio.h"
#include?"ace/OS_NS_string.h"
#include?"ace/Get_Opt.h"
#include?"ace/Configuration.h"
#include?"ace/Configuration_Import_Export.h"

int
HA_Status::init?(int?argc,?ACE_TCHAR?*argv[])


{
??static?const?ACE_TCHAR?options[]?=?ACE_TEXT?(":f:");
??ACE_Get_Opt?cmd_opts?(argc,?argv,?options,?0);
??if?(cmd_opts.long_option
????(ACE_TEXT?("config"),?'f',?ACE_Get_Opt::ARG_REQUIRED)?==?-1)
????return?-1;
??int?option;
??ACE_TCHAR?config_file[MAXPATHLEN];
??ACE_OS::strcpy?(config_file,?ACE_TEXT?("HAStatus.conf"));
??while?((option?=?cmd_opts?())?!=?EOF)
????switch?(option)

??
{
????case?'f':
??????ACE_OS::strncpy?(config_file,
????????cmd_opts.opt_arg?(),
????????MAXPATHLEN);
??????break;
????case?':':
??????ACE_ERROR_RETURN
????????((LM_ERROR,?ACE_TEXT?("-%c?requires?an?argument\n"),
????????cmd_opts.opt_opt?()),
????????-1);
????default:
??????ACE_ERROR_RETURN
????????((LM_ERROR,?ACE_TEXT?("Parse?error.\n")),?-1);
??}

??ACE_Configuration_Heap?config;
??config.open?();
??ACE_Registry_ImpExp?config_importer?(config);
??if?(config_importer.import_config?(config_file)?==?-1)
????ACE_ERROR_RETURN?((LM_ERROR,
????ACE_TEXT?("%p\n"),
????config_file),
????-1);

??ACE_Configuration_Section_Key?status_section;
??if?(config.open_section?(config.root_section?(),
????ACE_TEXT?("HAStatus"),
????0,
????status_section)?==?-1)
????ACE_ERROR_RETURN?((LM_ERROR,
????ACE_TEXT?("%p\n"),
????ACE_TEXT?("Can't?open?HAStatus?section")),
????-1);

??u_int?status_port;
??if?(config.get_integer_value?(status_section,
????ACE_TEXT?("ListenPort"),
????status_port)?==?-1)
????ACE_ERROR_RETURN?((LM_ERROR,
????ACE_TEXT?("HAStatus?ListenPort?does?")
????ACE_TEXT?("not?exist\n")),
????-1);
??this->listen_addr_.set?(static_cast<u_short>?(status_port));

??if?(this->acceptor_.open?(this->listen_addr_)?!=?0)
????ACE_ERROR_RETURN?((LM_ERROR,
????ACE_TEXT?("HAStatus?%p\n"),
????ACE_TEXT?("accept")),
????-1);
??ACE_DEBUG((LM_DEBUG,ACE_TEXT("listen?port?=?%d\n"),
????listen_addr_.get_port_number()));
??return?0;
}
//?Listing?1

//?Listing?2?code/ch19
int
HA_Status::fini?(void)


{
??this->acceptor_.close?();
??return?0;
}
//?Listing?2

//?Listing?3?code/ch19
int
HA_Status::info?(ACE_TCHAR?**str,?size_t?len)?const


{
??ACE_TCHAR?buf[BUFSIZ];
??ACE_OS::sprintf?(buf,?ACE_TEXT?("HAStatus?listening?on?port?%hu\n"),
????this->listen_addr_.get_port_number?());
??if?(*str?==?0)
????*str?=?ace::strnew?(buf);
??else
????ACE_OS::strncpy?(*str,?buf,?len);
??return?static_cast<int>?(ACE_OS::strlen?(*str));
}
//?Listing?3

//?Listing?4?code/ch19
ACE_FACTORY_DEFINE?(ACE_Local_Service,?HA_Status)

ACE_STATIC_SVC_DEFINE?(HA_Status_Descriptor,
???????????????????????ACE_TEXT?("HA_Status_Static_Service"),
???????????????????????ACE_SVC_OBJ_T,
???????????????????????&ACE_SVC_NAME?(HA_Status),
???????????????????????ACE_Service_Type::DELETE_THIS?|
???????????????????????ACE_Service_Type::DELETE_OBJ,
???????????????????????0)??//?Service?not?initially?active
ACE_STATIC_SVC_REQUIRE?(HA_Status_Descriptor)ClientHandler.h
//@file:?ClientHandler.h
//???????事件類
//@author:?AGP
#ifndef?CLIENT_HANDLER_H
#define?CLIENT_HANDLER_H
?
#include?"ace/SOCK_Stream.h"
#include?"ace/SOCK_Acceptor.h"
#include?"ace/Service_Object.h"
#include?"ace/Svc_Handler.h"

class?ClientHandler?:
??public?ACE_Svc_Handler<ACE_SOCK_STREAM,?ACE_NULL_SYNCH>


{
???typedef?ACE_Svc_Handler<ACE_SOCK_STREAM,?ACE_NULL_SYNCH>?BASE_T;
public:
??int?open(void*?=?0);
??virtual?int?handle_input(ACE_HANDLE?fd?=?ACE_INVALID_HANDLE);
??virtual?int?handle_output(ACE_HANDLE?fd?=?ACE_INVALID_HANDLE);
};
#endif
ClientHandler.cpp
//@file:?ClientHandler.cpp
//???????ClientHandler類的實現
#include?"ClientHandler.h"
#include?"ace/os.h"
#include?"ace/Time_Value.h"
#include?"ace/Message_Block.h"
int?ClientHandler::open(void*?p)


{
??ACE_DEBUG((LM_DEBUG,ACE_TEXT("open\n")));
??if?(BASE_T::open?(p)?==?-1)
????return?-1;

??ACE_TCHAR?peer_name[MAXHOSTNAMELEN];
??ACE_INET_Addr?peer_addr;
??if?(this->peer?().get_remote_addr?(peer_addr)?==?0?&&
????peer_addr.addr_to_string?(peer_name,?MAXHOSTNAMELEN)?==?0)
????ACE_DEBUG?((LM_DEBUG,
????ACE_TEXT?("(%P|%t)?Connection?from?%s\n"),
????peer_name));

??return?0;
}


int?ClientHandler::handle_input(ACE_HANDLE?fd?/**//*?=?ACE_INVALID_HANDLE?*/)


{
??ACE_DEBUG((LM_DEBUG,ACE_TEXT("handle_input\n")));
??const?size_t?INPUT_SIZE?=?4096;
??char?buffer[INPUT_SIZE];
??ssize_t?recv_cnt,?send_cnt;

??recv_cnt?=?this->peer?().recv?(buffer,?sizeof(buffer));
??if?(recv_cnt?<=?0)

??
{
????ACE_DEBUG?((LM_DEBUG,
??????ACE_TEXT?("(%P|%t)?Connection?closed\n")));
????return?-1;
??}
??buffer[recv_cnt]?=?0;

??send_cnt?=
????this->peer?().send?(buffer,
????ACE_static_cast?(size_t,?recv_cnt));
???ACE_DEBUG((LM_DEBUG,ACE_TEXT("收到的消息是[%s]\n"),buffer));
??if?(send_cnt?==?recv_cnt)
????return?0;
??if?(send_cnt?==?-1?&&?ACE_OS::last_error?()?!=?EWOULDBLOCK)
????ACE_ERROR_RETURN?((LM_ERROR,
????ACE_TEXT?("(%P|%t)?%p\n"),
????ACE_TEXT?("send")),
????0);
??if?(send_cnt?==?-1)
????send_cnt?=?0;
??ACE_Message_Block?*mb;
??size_t?remaining?=
????ACE_static_cast?(size_t,?(recv_cnt?-?send_cnt));
??ACE_NEW_RETURN
????(mb,?ACE_Message_Block?(&buffer[send_cnt],?remaining),?-1);
??int?output_off?=?this->msg_queue?()->is_empty?();
??ACE_Time_Value?nowait?(ACE_OS::gettimeofday?());
??if?(this->putq?(mb,?&nowait)?==?-1)

??
{
????ACE_ERROR?((LM_ERROR,
??????ACE_TEXT?("(%P|%t)?%p;?discarding?data\n"),
??????ACE_TEXT?("enqueue?failed")));
????mb->release?();
????return?0;
??}
??if?(output_off)
????return?this->reactor?()->register_handler
????(this,?ACE_Event_Handler::WRITE_MASK);
??return?0;

}


int?ClientHandler::handle_output(ACE_HANDLE?fd?/**//*?=?ACE_INVALID_HANDLE?*/)


{
??ACE_Message_Block?*mb;
??ACE_Time_Value?nowait?(ACE_OS::gettimeofday?());
??while?(-1?!=?this->getq?(mb,?&nowait))

??
{
????ssize_t?send_cnt?=
??????this->peer?().send?(mb->rd_ptr?(),?mb->length?());
????if?(send_cnt?==?-1)
??????ACE_ERROR?((LM_ERROR,
??????ACE_TEXT?("(%P|%t)?%p\n"),
??????ACE_TEXT?("send")));
????else
??????mb->rd_ptr?(ACE_static_cast?(size_t,?send_cnt));
????if?(mb->length?()?>?0)

????
{
??????this->ungetq?(mb);
??????break;
????}
????mb->release?();
??}
??return?(this->msg_queue?()->is_empty?())???-1?:?0;

}
特別說明,下面是某網友的問題
我在用ACE中Service-Config框架配置靜態服務時,出現下列錯誤:

error?C2146:?syntax?error?:?missing?';'?before?identifier?'ace_svc_desc_Time_Service_Descriptor'

error?C2501:?'ACE_Static_Svc_Descriptor'?:?missing?storage-class?or?type?specifiers

出錯的地方為:
ACE_STATIC_SVC_DEFINE(Time_Service_Descriptor,?
ACE_TEXT("time"),?ACE_SVC_OBJ_T,?
&ACE_SVC_NAME(TimeService),?ACE_Service_Type::DELETE_THIS|ACE_Service_Type::DELETE_OBJ,?1)?

問題所在
需要在HA_Status.cpp中包含,這一點是AGP書上未指明的
#include "