找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3768|回复: 6

linux下处理接受连接的事件处理器的问题

[复制链接]
发表于 2009-9-10 15:45:07 | 显示全部楼层 |阅读模式
写了一个基于Reactor的,用于接受网络连接的事件处理器。
注册的事件是ACCEPT_MASK,遇到的问题是:为什么在有一个客户端connect的时候,Reactor会回调handle_input很多次?

按书上说的,在有连接的时候,Reactor会回调handle_input通知程序处理这个连接。可是现在每来一个连接handle_input都会被回调
很多次。应该是一个连接来了,被回调一次才对啊。这是为什么呢?
发表于 2009-9-11 09:02:13 | 显示全部楼层
信息太少,楼主说的详细点。
 楼主| 发表于 2009-9-11 09:42:42 | 显示全部楼层

回复 #2 modern 的帖子

//我把代码贴上来,麻烦看一下
//这是我用来监听客户端连接的类

class CReactiveAcceptor : public ACE_Task<ACE_MT_SYNCH>
{
public:
        ~CReactiveAcceptor();
        int Open(CMainFrame *cmf);
        void Close();

        virtual int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE);
        virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask);

        virtual int svc (void);

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

private:
        int LoadConf();

private:
        int m_nClientIndex;                                                //为每一个连接分配一个序号
        unsigned int m_nPort;
        bool m_bRun;                                                        //接受处理器是否还要工作

protected:
        ACE_SOCK_Acceptor m_Acceptor;
        CMainFrame *m_pFrame;
};

/*********下边是这个类的handle_input方法*********************/
int CReactiveAcceptor::handle_input(ACE_HANDLE fd)
{
        //创建一个空消息,唤醒线程接受连接
        ACE_Message_Block *pMsg = new ACE_Message_Block(1, ACE_Message_Block::MB_DATA);
        putq(pMsg);
        return 0;
}


/********************问题见下边***************************/
在windows下工作正常,在linux下。每当有一个客户端调用ACE_SOCK_Connector::connect连接时,handle_input函数会被回调很多次,
如果在handle_input里边加一个调试信息的话,可以看到很多次打印信息,有好几百次。可是按说一个连接来了,应该被回调一次才对啊。
麻烦各位帮忙解释一下。
发表于 2009-9-11 12:37:47 | 显示全部楼层
如果是平台移植过程中出现的问题,原因可能很多,可能依赖于
Reactor在linux下楼主使用的是什么实现,windows下默认实现与linux默认实现是不一样的。
CReactiveAcceptor ::Open()函数的实现贴出来是必要的,ACE_SOCK_Acceptor的参数设置错误也可能导致一些未知的结果。
信息越多,越容易定位问题,希望楼主尽量把自己怀疑可能有问题的代码贴出来,不要我问一样提供一样。
 楼主| 发表于 2009-9-11 13:36:09 | 显示全部楼层

回复 #4 modern 的帖子

感谢modern的关注。我看了一下,在linux下,使用的是ACE_Select_Reactor

/*****************关键代码见下边**********************/
int CReactiveAcceptor::Open(CMainFrame *cmf)
{
        m_bRun = true;
        m_nClientIndex = 0;

        if(!cmf)
                return -1;
        m_pFrame = cmf;

        //这里边用了一个开源的读取XML的CPP读取配置文件
        if(LoadConf() < 0)
                return -1;

        //启动一个线程,线程内根据getq获得的消息类型,处理不同事务
        activate();

        //监听客户端连接
        ACE_INET_Addr listenAddr(m_nPort);
        if(m_Acceptor.open(listenAddr, 1) == -1)
        {
                MyDebug((LM_ERROR, _T("m_Acceptor.open(listenAddr, 1) == -1\n")));
                return -1;
        }

        return ( (ACE_Reactor::instance())->register_handler(this, ACE_Event_Handler::ACCEPT_MASK) );
}

/****************这是线程处理函数****************************/
int CReactiveAcceptor::svc(void)
{
        int nType;
        CServiceHandler *p = NULL;

        while(m_bRun)
        {
                ACE_Message_Block *mb;
                getq(mb);
                nType = mb->msg_type();
                mb->release();
                switch(nType)
                {
                case ACE_Message_Block::MB_DATA:
                        p = new CServiceHandler(m_nClientIndex++);
                        if(p)
                        {
                                if( (this->m_Acceptor.accept(p->;Peer())) == -1 )
                                {
                                        MyDebug((LM_ERROR, _T("accept connection error\n")));
                                        m_nClientIndex--;
                                        delete p;
                                }
                                else
                                {
                                        if(p->Open() < 0)
                                        {
                                                delete p;
                                                p = NULL;
                                                m_nClientIndex--;
                                                continue;
                                        }
                                        MyDebug((LM_INFO, _T("accept connection success\n")));
                                }
                        }//if(p)
                        break;
                case ACE_Message_Block::MB_HANGUP:
                        m_bRun = false;
                        return 0;
                default:
                        break;
                }        
        }//while

        return 0;
}

[ 本帖最后由 front_windy 于 2009-9-11 13:43 编辑 ]
发表于 2009-9-14 14:10:01 | 显示全部楼层
非常抱歉,才看到。怀疑问题出在这里。
int CReactiveAcceptor::handle_input(ACE_HANDLE fd)
{
        //创建一个空消息,唤醒线程接受连接
        ACE_Message_Block *pMsg = new ACE_Message_Block(1, ACE_Message_Block::MB_DATA);
        putq(pMsg);
        return 0;
}
怀疑是由于select与wfmo的平台差异导致的,
不过最近比较工作忙,没有时间验证,
楼主可以尝试直接在handle_input内处理,这里不要使用svc循环。
另外楼主可以参考一下APG7.6节的例子,或许会有帮助。
 楼主| 发表于 2009-9-14 16:46:08 | 显示全部楼层

回复 #6 modern 的帖子

谢谢modren,我会尽快尝试的。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-11-23 00:21 , Processed in 0.015981 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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