找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3719|回复: 1

请问handle_output怎么不能使用

[复制链接]
发表于 2008-5-15 11:22:06 | 显示全部楼层 |阅读模式
#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[128];

        int iLen = peer().recv(data, 128);
        if (iLen > 0)
        {
            data[iLen] = 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[64];
    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;
}


请问这是咋回事??
 楼主| 发表于 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);
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-11-22 17:58 , Processed in 0.018325 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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