rainfish 发表于 2008-5-15 11:22:06

请问handle_output怎么不能使用

#pragma comment(lib, "ACED.lib")

//利用的是reactor的acceptor-connector模式,在标准的reactor模式下亦如此。
//现象是第一次调用handle_output后没有问题,第二次调用时就不能用了,无法调用,不知道怎么回事。

#include "ace/Reactor.h"
#include "ace/Svc_Handler.h"
#include "ace/Connector.h"
#include "ace/Synch.h"
#include "ace/SOCK_Connector.h"

class My_Svc_Handler:
    public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>
{
public:
    int open(void*)
    {
      printf("Connection established\n");;
      //ACE_Reactor::instance()->register_handler(this, ACE_Event_Handler::WRITE_MASK);
      ACE_Reactor::instance()->register_handler(this, ACE_Event_Handler::READ_MASK);

      return 0;
    }

    int handle_input(ACE_HANDLE)
    {
      char data;

      int iLen = peer().recv(data, 128);
      if (iLen > 0)
      {
            data = 0;

            printf("receved : %s\n", data);
      }

      strcpy(data, "hello acceptor!");

      peer().send(data, strlen(data));
      
      ACE_Reactor::instance()->register_handler(this, ACE_Event_Handler::WRITE_MASK);

      return 0;

    }

    int handle_output(ACE_HANDLE)
    {
      char *data = "hello acceptor!";
      printf("handle_output\n");

      peer().send(data, strlen(data));

      return -1;
    }

    int handle_close(ACE_HANDLE, ACE_Reactor_Mask mask)
    {
      if (mask == ACE_Event_Handler::WRITE_MASK)
      {
            printf ("WRITE_MASK:handle_close\n");
            return 0;
      }
    }
};

typedef ACE_Connector<My_Svc_Handler,ACE_SOCK_CONNECTOR> MyConnector;

int main(int argc, char* argv[])
{
    ACE_INET_Addr addr(1500, "192.168.0.133");
    My_Svc_Handler *handler = new My_Svc_Handler;

    //instantiate the appropriate acceptor object with the address on which
    //we wish to accept and the Reactor instance we want to use. In this
    //case we just use the global ACE_Reactor singleton. (Read more about
    //the reactor in the previous chapter)
    MyConnector connector;
   
    if (connector.connect(handler, addr) == -1)
      ACE_ERROR((LM_ERROR, "%P|%t, %p", "Connection failed"));


    while(1)
      // Start the reactor’s event loop
      ACE_Reactor::instance()->handle_events();
}

//下边代码是不停地向其发送消息
// ace_socket1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


#include "ace/INET_Addr.h"
#include "ace/SOCK_Stream.h"
#include "ace/SOCK_Connector.h"
#include "ace/Log_Msg.h"
#include "ace/OS_NS_unistd.h"
#include "ace/Service_Config.h"

int
ACE_TMAIN(int argc,ACE_TCHAR *argv[])
{

    if (ACE_Service_Config::open(argc,
                                 argv,
                                 ACE_DEFAULT_LOGGER_KEY,
                                 1,
                                 0,
                                 1) < 0)
    {
      ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%p\n"), ACE_TEXT("Service Config open")), -1);
    }
   
    ACE_INET_Addr    srvr (44444, "192.168.0.133");//ACE_LOCALHOST);

    ACE_SOCK_Connector    connector;
    ACE_SOCK_Stream      peer;
    ACE_Time_Value      timeout(10);

    //if (-1 == connector.connect(peer, srvr))
    //    ACE_ERROR_RETURN ((LM_ERROR,
    //                        ACE_TEXT("%p\n"),
    //                        ACE_TEXT ("connect")),
    //                        1);
    ACE_OS::last_error(0);
    if (connector.connect(peer, srvr, &timeout)== -1)
    {
      if (ACE_OS::last_error() == ETIME)
      {
            ACE_DEBUG ((LM_DEBUG,
                        ACE_TEXT("(%p|%t) Timeout while"),
                        ACE_TEXT ("connecting to log server\n")));

      }
      else
      {
            ACE_ERROR((LM_ERROR,
                        ACE_TEXT("%p\n"),
                        ACE_TEXT("log")));
      }
      return 101;
    }
   
    int i = ACE_OS::last_error();
      
    printf("error: %d\n", i);   

    int    bc;
    char    buf;
    char    *ptr = "hello world!\n";

    //i = peer.send_n (ptr, strlen(ptr));
    //ACE_OS::sleep(5);
    do
    {
      i = peer.send_n (ptr, strlen(ptr));
      if (i>0)
            write (1, ptr, i);
   
      //ACE_OS::sleep(2);

         //i = peer.send_n (ptr, strlen(ptr));
         //if (i>0)
         //    write (1, ptr, i);

    /*    bc = peer.recv(buf, sizeof(buf));
    if (bc > 0)
      write (1, buf, bc);*/

      ACE_OS::sleep(2);
      
    }while(1);
   
    peer.close();


    //getchar();

    return 0;
}


请问这是咋回事??

rainfish 发表于 2008-5-15 14:24:54

在网上找了资料说更换反应器ACE_TP_Reactor就可以了,原因如下:Windows默认的反应器是ACE_WFMO_Reactor,它采用的是“边缘触发”方式,即内部使用的是 WaitForMultipleObjects(),只有状态变化(不可写变为可写)时才会被触发,所以在调用一次handle_ouput()后,由于状态一直可写,所以该函数不会再调用。有人也许会问,那为什么handle_input()为什么能一直被调用呢?那是因为你调用了recv()函数,该函数会使状态复位,所以只要是可读的时候handle_input()就会被调用。而ACE_TP_Reactor采用的是"水平触发"方式,即内部使用的是select()函数,只要是可写的,它就调用handle_output()。
ACE_TP_Reactor *tp_reactor = new ACE_TP_Reactor;
    ACE_Reactor *my_reactor = new ACE_Reactor(tp_reactor, 1);

    ACE_Reactor::instance(my_reactor, 1);
页: [1]
查看完整版本: 请问handle_output怎么不能使用