用ACE静态服务配置实现简单的Echo服务

用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

HA_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 " ace/service_config.h"

你可能感兴趣的:(用ACE静态服务配置实现简单的Echo服务)