Focus on ACE

订阅 ace-china
电子邮件:
浏览存于 groups.google.com 上的所有帖子

C++博客 首页 新随笔 联系 聚合 管理
  64 Posts :: 3 Stories :: 22 Comments :: 0 Trackbacks
用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_;

}
;
#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"
posted on 2006-04-17 13:55 Stone Jiang 阅读(2140) 评论(0)  编辑 收藏 引用 所属分类: ACE

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理