找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 6174|回复: 4

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

[复制链接]
发表于 2008-5-21 23:21:24 | 显示全部楼层 |阅读模式
下面的代码,编译成可执行程序,可以以带参数和不带参数方式运行,不带参数运行时程序在主线程中监听3000端口
并执行Reactor事件循环,带参数(任意参数均可)运行时程序启动一个线程,在线程中监听3000端口并执行Reactor
事件循环。我遇到的问题是在Linux平台下以带参数方式运行程序,Reactor事件驱动不起来,接受连接和收到数据时都没有回调
相应的函数。而在Windows平台下则一切正常。这是为什么呢?该怎么解决?
  1. #include "ace/OS.h"
  2. #include "ace/Thread_Manager.h"
  3. #include "ace/Reactor.h"
  4. #include "ace/SOCK_Connector.h"
  5. #include "ace/SOCK_Acceptor.h"
  6. #include "ace/Auto_Ptr.h"
  7. #include "ace/Log_Msg.h"
  8. class ClientService : public ACE_Event_Handler
  9. {
  10. public:
  11. ACE_SOCK_Stream &peer(void)
  12. {
  13.   return this->sock_;
  14. } int open(void)
  15. {
  16.   return this->reactor()->register_handler(this, ACE_Event_Handler::READ_MASK);
  17. } virtual ACE_HANDLE get_handle(void) const
  18. {
  19.   return this->sock_.get_handle();
  20. } virtual int handle_input(ACE_HANDLE fd)
  21. {
  22.   // 一个简单的EchoServer,将客户端的信息返回    int rev = peer().recv(buf, 100);
  23.   if (rev <= 0)
  24.    return -1;  ACE_DEBUG((LM_DEBUG, ACE_TEXT("receive data\n")));  peer().send(buf, rev);  return 0;
  25. } // 释放相应资源 virtual int handle_close(ACE_HANDLE, ACE_Reactor_Mask mask)
  26. {
  27.   if (mask == ACE_Event_Handler::WRITE_MASK)
  28.    return 0;  mask = ACE_Event_Handler::ALL_EVENTS_MASK |
  29.    ACE_Event_Handler::DONT_CALL;
  30.   this->reactor()->remove_handler (this, mask);  this->sock_.close();  delete this;  ACE_DEBUG((LM_DEBUG, ACE_TEXT("connection closed\n")));  return 0;
  31. }protected:
  32. char buf[100];
  33. ACE_SOCK_Stream sock_;
  34. };class ClientAcceptor : public ACE_Event_Handler
  35. {
  36. public:
  37. virtual ~ClientAcceptor()
  38. {
  39.   this->handle_close (ACE_INVALID_HANDLE, 0);
  40. } int open(const ACE_INET_Addr &listen_addr)
  41. {
  42.   if (this->acceptor_.open(listen_addr, 1) == -1)
  43.   {
  44.    ACE_OS::printf("open port fail");
  45.    return -1;
  46.   }  // 注册接受连接回调事件    return this->reactor()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);
  47. } virtual ACE_HANDLE get_handle(void) const
  48. {
  49.   return this->acceptor_.get_handle();
  50. } virtual int handle_input(ACE_HANDLE fd )
  51. {
  52.   ClientService *client = new ClientService();
  53.   auto_ptr<ClientService> p(client);  if (this->acceptor_.accept(client->peer()) == -1)
  54.   {
  55.    ACE_DEBUG((LM_DEBUG, ACE_TEXT("accept client fail")));
  56.    return -1;
  57.   }
  58.   ACE_DEBUG((LM_DEBUG, ACE_TEXT("aceept a client\n")));  p.release();
  59.   client->reactor(this->reactor());
  60.   if (client->open() == -1)
  61.    client->handle_close (ACE_INVALID_HANDLE, 0);  return 0;
  62. } virtual int handle_close(ACE_HANDLE handle,
  63.   ACE_Reactor_Mask close_mask)
  64. {
  65.   if (this->acceptor_.get_handle() != ACE_INVALID_HANDLE)
  66.   {
  67.    ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK |
  68.     ACE_Event_Handler::DONT_CALL;
  69.    this->reactor()->remove_handler(this, m);
  70.    this->acceptor_.close();
  71.   }
  72.   return 0;
  73. }protected:
  74. ACE_SOCK_Acceptor acceptor_;
  75. };ACE_THR_FUNC_RETURN event_loop(void* pPara)
  76. {
  77. ACE_DEBUG((LM_DEBUG, ACE_TEXT("event_loop\n"))); ACE_INET_Addr addr(3000);
  78. ClientAcceptor server;
  79. server.reactor(ACE_Reactor::instance());
  80. server.open(addr);
  81. ACE_DEBUG((LM_DEBUG, ACE_TEXT("listen on port : 3000\n"))); while(true)
  82. {
  83.   ACE_Reactor::instance()->handle_events();
  84. }
  85. }int main(int argc, char *argv[])
  86. {
  87. if (argc == 1)
  88. {
  89.   ACE_INET_Addr addr(3000);
  90.   ClientAcceptor server;
  91.   server.reactor(ACE_Reactor::instance());
  92.   server.open(addr);
  93.   ACE_DEBUG((LM_DEBUG, ACE_TEXT("listen on port : 3000\n")));  while(true)
  94.   {
  95.    ACE_Reactor::instance()->handle_events();
  96.   }
  97. }
  98. else
  99. {
  100.   ACE_Thread_Manager::instance()->spawn_n(1, event_loop, ACE_Reactor::instance());
  101. } ACE_Thread_Manager::instance()->wait(); return 0;
  102. }
复制代码
 楼主| 发表于 2008-5-21 23:21:37 | 显示全部楼层
event_loop
reactor->owner(ACE_OS::thr_self());
 楼主| 发表于 2008-5-21 23:21:52 | 显示全部楼层
能说明一下收不到回调事件的原因吗?

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

其owner_成员变量有什么作用?
 楼主| 发表于 2008-5-21 23:22:00 | 显示全部楼层
APG里面记得有说明的。是因为工作模型的原因,领导者/跟随者,领导者需要设置这个。
发表于 2009-1-9 14:52:26 | 显示全部楼层
我刚好在做服务器移植时遇到这个问题,也是在Windows平台下正常,在Linux平台下注册的Acceptor的handle_input不会被调用,在google上搜到了这篇文章,但是看了还是不怎么理解,谁能给解释下,并给出一个解决方法吗?非常感谢!
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-5-7 16:34 , Processed in 0.022972 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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