找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 5014|回复: 2

关于ACE_Event_Handler

[复制链接]
发表于 2011-11-25 21:08:58 | 显示全部楼层 |阅读模式
大家好,有关ACE_Event_Handler的问题,需要请教大家。源代码和问题如下:
服务端代码:
  1. #include "stdafx.h"
  2. #include <ace/OS.h>
  3. #include <ace/Reactor.h>
  4. #include <ace/SOCK_Connector.h>
  5. #include <ace/SOCK_Acceptor.h>
  6. #include <ace/Auto_Ptr.h>
  7. #include <iostream>
  8. #pragma comment(lib, "ace.lib")
  9. #pragma comment(lib, "aced.lib")
  10. class ClientService : public ACE_Event_Handler
  11. {
  12. public:
  13.     ACE_SOCK_Stream &peer (void) { return this->sock_; }
  14.     int open (void)
  15.     {
  16.         //注册读就绪回调函数
  17.         return this->reactor ()->register_handler(this, ACE_Event_Handler::READ_MASK);
  18.     }
  19.     virtual ACE_HANDLE get_handle (void) const { return this->sock_.get_handle (); }
  20.     virtual int handle_input (ACE_HANDLE fd )
  21.     {
  22.         //一个简单的EchoServer,将客户端的信息返回
  23.         int rev = peer().recv(buf,100);
  24.         if(rev<=0)
  25.             return -1;
  26.         buf[rev]='\0';
  27.         std::cout<<"Receive from client:"<<buf<<std::endl;
  28.         peer().send(buf,rev);
  29.         std::cout<<"Send to client:"<<buf<<std::endl;
  30.         return 0;
  31.     }
  32.     // 释放相应资源
  33.     virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask mask)
  34.     {
  35.         if (mask == ACE_Event_Handler::WRITE_MASK)
  36.             return 0;
  37.         mask = ACE_Event_Handler::ALL_EVENTS_MASK |
  38.             ACE_Event_Handler::DONT_CALL;
  39.         this->reactor ()->remove_handler (this, mask);
  40.         this->sock_.close ();
  41.         delete this;    //socket出错时,将自动删除该客户端,释放相应资源
  42.         return 0;
  43.     }
  44. protected:
  45.     char buf[100];
  46.     ACE_SOCK_Stream sock_;
  47. };
  48. class ClientAcceptor : public ACE_Event_Handler
  49. {
  50. public:
  51.     virtual ~ClientAcceptor (){this->handle_close (ACE_INVALID_HANDLE, 0);}
  52.     int open (const ACE_INET_Addr &listen_addr)
  53.     {
  54.         if (this->acceptor_.open (listen_addr, 1) == -1)
  55.         {
  56.             ACE_OS::printf("open port fail");
  57.             return -1;
  58.         }
  59.         //注册接受连接回调事件
  60.         return this->reactor ()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);
  61.     }
  62.     virtual ACE_HANDLE get_handle (void) const
  63.     { return this->acceptor_.get_handle (); }
  64.     virtual int handle_input (ACE_HANDLE fd )
  65.     {
  66.         ClientService *client = new ClientService();
  67.         auto_ptr<ClientService> p (client);
  68.         if (this->acceptor_.accept (client->peer ()) == -1)
  69.         {
  70.             ACE_OS::printf("accept client fail \n");
  71.             return -1;
  72.         }
  73.         p.release ();
  74.         client->reactor (this->reactor ());
  75.         if (client->open () == -1)
  76.             client->handle_close (ACE_INVALID_HANDLE, 0);
  77.         return 0;
  78.     }
  79.     virtual int handle_close (ACE_HANDLE handle,
  80.         ACE_Reactor_Mask close_mask)
  81.     {
  82.         if (this->acceptor_.get_handle () != ACE_INVALID_HANDLE)
  83.         {
  84.             ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK |
  85.                 ACE_Event_Handler::DONT_CALL;
  86.             this->reactor ()->remove_handler (this, m);
  87.             this->acceptor_.close ();
  88.         }
  89.         return 0;
  90.     }
  91. protected:
  92.     ACE_SOCK_Acceptor acceptor_;
  93. };
  94. int main(int argc, char *argv[])
  95. {
  96.     ACE_INET_Addr addr(3000,"127.0.0.1");
  97.     ClientAcceptor server;
  98.     server.reactor(ACE_Reactor::instance());
  99.     server.open(addr);
  100.     while(true)
  101.     {
  102.         ACE_Reactor::instance()->handle_events();
  103.     }
  104.     return 0;
  105. }
复制代码
客户端代码:
  1. #include "stdafx.h"
  2. #include <iostream>
  3. #include <string>
  4. #include <ace/ACE.h>
  5. #include <ace/INET_Addr.h>
  6. #include <ace/SOCK_Connector.h>
  7. #include <ace/SOCK_Stream.h>
  8. #pragma comment(lib, "ace.lib")
  9. #pragma comment(lib, "aced.lib")
  10. int _tmain(int argc, _TCHAR* argv[])
  11. {
  12.     ACE::init();
  13.     std::string str="Hello Server \n";
  14.     ACE_INET_Addr svr_addr(3000, "127.0.0.1");
  15.     ACE_SOCK_STREAM stream;
  16.     ACE_SOCK_Connector connector;
  17.     int ret=connector.connect(stream, svr_addr);
  18.     if(0 != ret)
  19.     {
  20.         std::cout<<"Error in connect"<<std::endl;
  21.         return -1;
  22.     }
  23.     std::cout<<"sending data:"<<std::endl<<str<<std::endl;
  24.     ret=stream.send(str.c_str(), str.length());
  25.     if(-1 == ret)
  26.     {
  27.         std::cout<<"Error in send"<<std::endl;
  28.         return -1;
  29.     }
  30.     str.erase();
  31.     str.resize(1024);
  32.     ret=stream.recv((void *)str.c_str(), str.length());
  33.     if(-1 == ret)
  34.     {
  35.         std::cout<<"Error in recv"<<std::endl;
  36.         return -1;
  37.     }
  38.     std::cout<<"recived data::"<<std::endl<<str<<std::endl;
  39.     ACE::fini();
  40.     return 0;
  41. }
复制代码
请问:
客户端socket只发送了一次数据给服务端,但是为什么ClientService的handle_input会执行两次呢?
谢谢大家!
发表于 2011-11-30 14:07:45 | 显示全部楼层
估计你是在win下面跑,默认使用ACE_WFMO_Reacotr,该复用是边缘触发方式,
当你recv后,状态复位,由可读变为不可读,使得读事件再度被激发,其中未必真的有数据到达。
发表于 2011-12-1 15:14:03 | 显示全部楼层
今天再次阅读发现自己的回答有误,更正下。
第二次触发应该是你socket关闭产生的事件,而且是非优雅的关闭,recv返回-1,楼主大意了
我说的那个lt/et的问题应该是output中有所区别,特此说明
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-5-7 23:07 , Processed in 0.017468 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表