找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 5046|回复: 9

register_handler(this, ACE_Event_Handler::READ_MASK)失败

[复制链接]
发表于 2009-4-7 09:57:56 | 显示全部楼层 |阅读模式
基于反应器框架,我写了2个类,可是总是在注册“读事件”时失败,请版主帮忙找找问题所在。
class MyConnection: public ACE_Event_Handler
{
public:
       MyConnection();
      virtual ~MyConnection();
      int init_as_client_bindip(const char *szIP);     // 作为UDP客户端绑定IP
      // get remote address of this connection
    virtual int get_remote_addr(ACE_INET_Addr& addr);

    virtual int handle_timeout (const ACE_Time_Value &tv, const void *act = 0)
    {
       return 0;
    }
    virtual int handle_input (ACE_HANDLE handle);
    virtual int handle_close (ACE_HANDLE handle,ACE_Reactor_Mask close_mask);      

protected:
    // parse received msg
    virtual int on_msg (ACE_UINT8 msg_type, MessageBlock* mb) = 0;

private:
    ACE_SOCK_Dgram m_dgram;
}

class MyClient : public MyConnection
{
public:
      MyClient();
      virtual ~MyClient();
      virtual int handle_timeout (const ACE_Time_Value &tv, const void *act = 0);
protected:
      // 定一些业务上处理的方法,与所提的问题无关,下面就不列出来了
      .............
}


我的注册函数写在MyConnection类的构造函数中,是这样写的:
if ( -1 == ACE_Reactor::instance ()->register_handler(this, ACE_Event_Handler::READ_MASK) )
{
     printf("ACE_Reactor::MyConnection register_handler failed.");
}
此时总是失败。我想假若在构造的时候不能注册,是不是构造之后就可以注册了?后来,我把注册函数移到对象构造成功之后,
即用下面代码
if ( -1 == ACE_Reactor::instance ()->register_handler(对象指针, ACE_Event_Handler::READ_MASK) )
{
     printf("ACE_Reactor::MyConnection register_handler failed.");
}
可是还是注册失败。
发表于 2009-4-7 10:36:58 | 显示全部楼层
你应该要有一个
ACE_HANDLE get_handle (void) const;
返回UDP SOCKET  本地 ACE_SOCK_Dgram的句柄
 楼主| 发表于 2009-4-7 10:39:17 | 显示全部楼层
我在UDPConnection类加了下面的函数
virtual ACE_HANDLE get_handle (void) const
    {
               return this->m_dgram.get_handle();
    }
可是注册仍然失败
发表于 2009-4-7 11:01:23 | 显示全部楼层

回复 #3 xiaokousky 的帖子

注册失败返回什么出错信息?
No such device or address?
 楼主| 发表于 2009-4-7 14:14:08 | 显示全部楼层
if ( -1 == ACE_Reactor::instance ()->register_handler(this, ACE_Event_Handler::READ_MASK) )
{
      ACE_DEBUG((LM_ERROR, ACE_TEXT("%p\n"), ACE_TEXT("ACE_Reactor::MyConnection register_handler failed")));
}

打印信息如下:
ACE_Reactor::UDPConnection register_handler failed: Invalid argument
 楼主| 发表于 2009-4-7 15:47:45 | 显示全部楼层
终于发现问题所在!
问题出在int init_as_client_bindip(const char *szIP);     // 作为UDP客户端绑定IP
这个函数在前摄器模式下工作OK,到linux epoll模式下,绑定端口后,再进行注册“读事件”会失败。


int MyConnection::init_as_client_bindip(const char *szIP)
{
    // Create a UDP socket to transfer datagrams.
    ACE_SOCK_Dgram sock;
    ACE_INET_Addr ace_addr;
    sockaddr_in sockaddr;
    ACE_UINT16 localPort = 32500;

    do
    {
        memset(&sockaddr, 0, sizeof(sockaddr_in));
        sockaddr.sin_family = AF_INET;
        sockaddr.sin_port = htons(localPort++);
        sockaddr.sin_addr.s_addr = inet_addr(szIP);
        ACE_INET_Addr ace_addr_temp(&sockaddr, sizeof(sockaddr_in));
        ace_addr = ace_addr_temp;
        if (localPort-32500>100)
        {
            ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open udp socket failed"), -1);
            return -1;
        }
    }
    while (m_dgram.open(ace_addr, ACE_PROTOCOL_FAMILY_INET, 0, 1) == -1);
   printf.StatusOut("Bind local UDP socket at port %d.", localPort-1);
    return 0;
}

换成下面的函数,程序就OK了(上面的绑定本地IP和端口的函数在前摄器模式下工作OK)
int MyConnection::init_as_client ()
{
    // Create a UDP socket to transfer datagrams.
    if (m_dgram.open (ACE_INET_Addr::sap_any) == -1)
        ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open udp socket failed"), -1);
    return 0;
}
 楼主| 发表于 2009-4-7 16:13:01 | 显示全部楼层
为什么不能绑定本机IP和端口呢?
比如本机有两张网卡,绑定本机指定的IP和端口的应用是存在的。
在前摄器模式下工作very good
在linux epoll模式下,难道不能绑定UDP ip和端口?又或者是在此模式下需要其他方式绑定IP,其他函数来绑定IP?
发表于 2009-4-7 17:28:35 | 显示全部楼层
因为你使用的是udp协议ACE_SOCK_Dgram,所以在注册READ_MASK事件之前,必须先指定在本地的监听端口.

按照你提供的代码来看,你应该在调用register_handler()之前增加如下代码即可:
ACE_INET_Addr m_localAddr;      //这个你查一下构造函数初始化一下
m_dgram.open(m_localAddr);

if ( -1 == ACE_Reactor::instance ()->register_handler(this, ACE_Event_Handler::READ_MASK) )
{
     printf("ACE_Reactor::MyConnection register_handler failed.");
}
发表于 2009-4-7 17:31:44 | 显示全部楼层
原帖由 xiaokousky 于 2009-4-7 15:47 发表
终于发现问题所在!
问题出在int init_as_client_bindip(const char *szIP);     // 作为UDP客户端绑定IP
这个函数在前摄器模式下工作OK,到linux epoll模式下,绑定端口后,再进行注册“读事件”会失败。


int MyConnectio ...




回复完了才看到.............晕死.....
 楼主| 发表于 2009-4-8 13:51:32 | 显示全部楼层
有没有方法在linux epoll模式下,绑定本地指定的IP和端口?
我在用上面发放绑定IP,端口后,注册读事件失败。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-11-23 03:58 , Processed in 0.025172 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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