chennut0802 发表于 2011-11-25 21:08:58

关于ACE_Event_Handler

大家好,有关ACE_Event_Handler的问题,需要请教大家。源代码和问题如下:
服务端代码:#include "stdafx.h"
#include <ace/OS.h>
#include <ace/Reactor.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Acceptor.h>
#include <ace/Auto_Ptr.h>
#include <iostream>

#pragma comment(lib, "ace.lib")
#pragma comment(lib, "aced.lib")

class ClientService : public ACE_Event_Handler
{
public:
    ACE_SOCK_Stream &peer (void) { return this->sock_; }

    int open (void)
    {
      //注册读就绪回调函数
      return this->reactor ()->register_handler(this, ACE_Event_Handler::READ_MASK);
    }

    virtual ACE_HANDLE get_handle (void) const { return this->sock_.get_handle (); }

    virtual int handle_input (ACE_HANDLE fd )
    {
      //一个简单的EchoServer,将客户端的信息返回
      int rev = peer().recv(buf,100);
      if(rev<=0)
            return -1;
      buf='\0';
      std::cout<<"Receive from client:"<<buf<<std::endl;


      peer().send(buf,rev);
      std::cout<<"Send to client:"<<buf<<std::endl;
      return 0;
    }

    // 释放相应资源
    virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask mask)
    {
      if (mask == ACE_Event_Handler::WRITE_MASK)
            return 0;
      mask = ACE_Event_Handler::ALL_EVENTS_MASK |
            ACE_Event_Handler::DONT_CALL;
      this->reactor ()->remove_handler (this, mask);
      this->sock_.close ();
      delete this;    //socket出错时,将自动删除该客户端,释放相应资源
      return 0;
    }

protected:
    char buf;
    ACE_SOCK_Stream sock_;
};

class ClientAcceptor : public ACE_Event_Handler
{
public:
    virtual ~ClientAcceptor (){this->handle_close (ACE_INVALID_HANDLE, 0);}

    int open (const ACE_INET_Addr &listen_addr)
    {
      if (this->acceptor_.open (listen_addr, 1) == -1)
      {
            ACE_OS::printf("open port fail");
            return -1;
      }
      //注册接受连接回调事件
      return this->reactor ()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);
    }

    virtual ACE_HANDLE get_handle (void) const
    { return this->acceptor_.get_handle (); }

    virtual int handle_input (ACE_HANDLE fd )
    {
      ClientService *client = new ClientService();
      auto_ptr<ClientService> p (client);

      if (this->acceptor_.accept (client->peer ()) == -1)
      {
            ACE_OS::printf("accept client fail \n");
            return -1;
      }
      p.release ();
      client->reactor (this->reactor ());
      if (client->open () == -1)
            client->handle_close (ACE_INVALID_HANDLE, 0);
      return 0;
    }

    virtual int handle_close (ACE_HANDLE handle,
      ACE_Reactor_Mask close_mask)
    {
      if (this->acceptor_.get_handle () != ACE_INVALID_HANDLE)
      {
            ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK |
                ACE_Event_Handler::DONT_CALL;
            this->reactor ()->remove_handler (this, m);
            this->acceptor_.close ();
      }
      return 0;
    }

protected:
    ACE_SOCK_Acceptor acceptor_;
};

int main(int argc, char *argv[])
{
    ACE_INET_Addr addr(3000,"127.0.0.1");
    ClientAcceptor server;
    server.reactor(ACE_Reactor::instance());
    server.open(addr);

    while(true)
    {
      ACE_Reactor::instance()->handle_events();
    }

    return 0;
}

客户端代码:#include "stdafx.h"
#include <iostream>
#include <string>

#include <ace/ACE.h>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>

#pragma comment(lib, "ace.lib")
#pragma comment(lib, "aced.lib")

int _tmain(int argc, _TCHAR* argv[])
{
    ACE::init();
    std::string str="Hello Server \n";

    ACE_INET_Addr svr_addr(3000, "127.0.0.1");
    ACE_SOCK_STREAM stream;

    ACE_SOCK_Connector connector;
    int ret=connector.connect(stream, svr_addr);
    if(0 != ret)
    {
      std::cout<<"Error in connect"<<std::endl;
      return -1;
    }

    std::cout<<"sending data:"<<std::endl<<str<<std::endl;
    ret=stream.send(str.c_str(), str.length());
    if(-1 == ret)
    {
      std::cout<<"Error in send"<<std::endl;
      return -1;
    }

    str.erase();
    str.resize(1024);
    ret=stream.recv((void *)str.c_str(), str.length());
    if(-1 == ret)
    {
      std::cout<<"Error in recv"<<std::endl;
      return -1;
    }

    std::cout<<"recived data::"<<std::endl<<str<<std::endl;
    ACE::fini();
    return 0;
}
请问:
客户端socket只发送了一次数据给服务端,但是为什么ClientService的handle_input会执行两次呢?
谢谢大家!

wesom 发表于 2011-11-30 14:07:45

估计你是在win下面跑,默认使用ACE_WFMO_Reacotr,该复用是边缘触发方式,
当你recv后,状态复位,由可读变为不可读,使得读事件再度被激发,其中未必真的有数据到达。

wesom 发表于 2011-12-1 15:14:03

今天再次阅读发现自己的回答有误,更正下。
第二次触发应该是你socket关闭产生的事件,而且是非优雅的关闭,recv返回-1,楼主大意了
我说的那个lt/et的问题应该是output中有所区别,特此说明
页: [1]
查看完整版本: 关于ACE_Event_Handler