用ACE静态服务配置实现简单的Echo服务
用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<[email protected]>
//
@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_;
![]()
}
;
#endif
//
@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)
//
@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
//
@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 " ace/service_config.h"
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
HA_Status.h
HA_Status.cpp
ClientHandler.h
ClientHandler.cpp
特别说明,下面是某网友的问题
问题所在
需要在HA_Status.cpp中包含,这一点是AGP书上未指明的
#include " ace/service_config.h"