linux下处理接受连接的事件处理器的问题
写了一个基于Reactor的,用于接受网络连接的事件处理器。注册的事件是ACCEPT_MASK,遇到的问题是:为什么在有一个客户端connect的时候,Reactor会回调handle_input很多次?
按书上说的,在有连接的时候,Reactor会回调handle_input通知程序处理这个连接。可是现在每来一个连接handle_input都会被回调
很多次。应该是一个连接来了,被回调一次才对啊。这是为什么呢? 信息太少,楼主说的详细点。
回复 #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里边加一个调试信息的话,可以看到很多次打印信息,有好几百次。可是按说一个连接来了,应该被回调一次才对啊。
麻烦各位帮忙解释一下。 如果是平台移植过程中出现的问题,原因可能很多,可能依赖于
Reactor在linux下楼主使用的是什么实现,windows下默认实现与linux默认实现是不一样的。
CReactiveAcceptor ::Open()函数的实现贴出来是必要的,ACE_SOCK_Acceptor的参数设置错误也可能导致一些未知的结果。
信息越多,越容易定位问题,希望楼主尽量把自己怀疑可能有问题的代码贴出来,不要我问一样提供一样。
回复 #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 编辑 ] 非常抱歉,才看到。怀疑问题出在这里。
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节的例子,或许会有帮助。
回复 #6 modern 的帖子
谢谢modren,我会尽快尝试的。
页:
[1]