peakzhang 发表于 2008-5-21 23:21:24

Linux下如何在多线程中使用Reactor?

下面的代码,编译成可执行程序,可以以带参数和不带参数方式运行,不带参数运行时程序在主线程中监听3000端口
并执行Reactor事件循环,带参数(任意参数均可)运行时程序启动一个线程,在线程中监听3000端口并执行Reactor
事件循环。我遇到的问题是在Linux平台下以带参数方式运行程序,Reactor事件驱动不起来,接受连接和收到数据时都没有回调
相应的函数。而在Windows平台下则一切正常。这是为什么呢?该怎么解决?#include "ace/OS.h"
#include "ace/Thread_Manager.h"
#include "ace/Reactor.h"
#include "ace/SOCK_Connector.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/Auto_Ptr.h"
#include "ace/Log_Msg.h"


class ClientService : public ACE_Event_Handler
{
public:
ACE_SOCK_Stream &peer(void)
{
return this->sock_;
} int open(void)
{
return this->reactor()->register_handler(this, ACE_Event_Handler::READ_MASK);
} virtual ACE_HANDLE get_handle(void) const
{
return this->sock_.get_handle();
} virtual int handle_input(ACE_HANDLE fd)
{
// 一个简单的EchoServer,将客户端的信息返回    int rev = peer().recv(buf, 100);
if (rev <= 0)
   return -1;ACE_DEBUG((LM_DEBUG, ACE_TEXT("receive data\n")));peer().send(buf, rev);return 0;
} // 释放相应资源 virtual int handle_close(ACE_HANDLE, ACE_Reactor_Mask mask)
{
if (mask == ACE_Event_Handler::WRITE_MASK)
   return 0;mask = ACE_Event_Handler::ALL_EVENTS_MASK |
   ACE_Event_Handler::DONT_CALL;
this->reactor()->remove_handler (this, mask);this->sock_.close();delete this;ACE_DEBUG((LM_DEBUG, ACE_TEXT("connection closed\n")));return 0;
}protected:
char buf;
ACE_SOCK_Stream sock_;
};class ClientAcceptor : public ACE_Event_Handler
{
public:
virtual ~ClientAcceptor()
{
this->handle_close (ACE_INVALID_HANDLE, 0);
} int open(const ACE_INET_Addr &listen_addr)
{
if (this->acceptor_.open(listen_addr, 1) == -1)
{
   ACE_OS::printf("open port fail");
   return -1;
}// 注册接受连接回调事件    return this->reactor()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);
} virtual ACE_HANDLE get_handle(void) const
{
return this->acceptor_.get_handle();
} virtual int handle_input(ACE_HANDLE fd )
{
ClientService *client = new ClientService();
auto_ptr<ClientService> p(client);if (this->acceptor_.accept(client->peer()) == -1)
{
   ACE_DEBUG((LM_DEBUG, ACE_TEXT("accept client fail")));
   return -1;
}
ACE_DEBUG((LM_DEBUG, ACE_TEXT("aceept a client\n")));p.release();
client->reactor(this->reactor());
if (client->open() == -1)
   client->handle_close (ACE_INVALID_HANDLE, 0);return 0;
} virtual int handle_close(ACE_HANDLE handle,
ACE_Reactor_Mask close_mask)
{
if (this->acceptor_.get_handle() != ACE_INVALID_HANDLE)
{
   ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK |
    ACE_Event_Handler::DONT_CALL;
   this->reactor()->remove_handler(this, m);
   this->acceptor_.close();
}
return 0;
}protected:
ACE_SOCK_Acceptor acceptor_;
};ACE_THR_FUNC_RETURN event_loop(void* pPara)
{
ACE_DEBUG((LM_DEBUG, ACE_TEXT("event_loop\n"))); ACE_INET_Addr addr(3000);
ClientAcceptor server;
server.reactor(ACE_Reactor::instance());
server.open(addr);
ACE_DEBUG((LM_DEBUG, ACE_TEXT("listen on port : 3000\n"))); while(true)
{
ACE_Reactor::instance()->handle_events();
}
}int main(int argc, char *argv[])
{
if (argc == 1)
{
ACE_INET_Addr addr(3000);
ClientAcceptor server;
server.reactor(ACE_Reactor::instance());
server.open(addr);
ACE_DEBUG((LM_DEBUG, ACE_TEXT("listen on port : 3000\n")));while(true)
{
   ACE_Reactor::instance()->handle_events();
}
}
else
{
ACE_Thread_Manager::instance()->spawn_n(1, event_loop, ACE_Reactor::instance());
} ACE_Thread_Manager::instance()->wait(); return 0;
}

peakzhang 发表于 2008-5-21 23:21:37

event_loop
reactor->owner(ACE_OS::thr_self());

peakzhang 发表于 2008-5-21 23:21:52

能说明一下收不到回调事件的原因吗?

以及加reactor->owner(ACE_OS::thr_self());的原因?在linux下,缺省使用ACE_Select_Reactor, 问题是

其owner_成员变量有什么作用?

peakzhang 发表于 2008-5-21 23:22:00

APG里面记得有说明的。是因为工作模型的原因,领导者/跟随者,领导者需要设置这个。

holyn2002 发表于 2009-1-9 14:52:26

我刚好在做服务器移植时遇到这个问题,也是在Windows平台下正常,在Linux平台下注册的Acceptor的handle_input不会被调用,在google上搜到了这篇文章,但是看了还是不怎么理解,谁能给解释下,并给出一个解决方法吗?非常感谢!
页: [1]
查看完整版本: Linux下如何在多线程中使用Reactor?