首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络协议 >

linux下基于ACE的udp服务器有关问题

2012-03-03 
linux下基于ACE的udp服务器问题环境:centOS + ACE 5.7问题:采用reactor框架,同样的代码在windows平台上很

linux下基于ACE的udp服务器问题
环境:centOS + ACE 5.7 
问题:采用reactor框架,同样的代码在windows平台上很好,但在linux下失败。
代码如下:

==============================================================
启动的地方:
ACE_INET_Addr local_addr( 9005 );
CUDPRequestHandler* lpUdpHandler = NULL;
ACE_NEW_RETURN( lpUdpHandler, CUDPRequestHandler(local_addr), -1 );
if ( ACE_Reactor::instance()->register_handler( lpUdpHandler, ACE_Event_Handler::READ_MASK ) == -1 )
{
  return -1;
}
CGUDPServer* lpUdpServer = NULL;
ACE_NEW_RETURN( lpUdpServer, CGUDPServer, -1 );
lpUdpServer->activate( THR_NEW_LWP|THR_JOINABLE, 4 );

==============================================================
CGUDPServer 代码
class CGUDPServer : public ACE_Task_Base
  {
  public:

  virtual int svc(void);

  virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask);

  };

  int CGUDPServer::svc(void)
  {
  int nResult = ACE_Reactor::instance()->run_reactor_event_loop(); // ?????????出现问题的地方?????
  if ( nResult == -1 )
  {
  return -1;
  }
  return 0;
  }

  int CGUDPServer::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask)
  {
  delete this;
  return 0;
  }

==============================================================
CUDPRequestHandler代码:
class CUDPRequestHandler : public ACE_Event_Handler 
  {
  public:
  CUDPRequestHandler( const ACE_INET_Addr& local_addr );
  ~CUDPRequestHandler();

  virtual ACE_HANDLE get_handle(void) const;

  virtual int handle_input(ACE_HANDLE fd /* = ACE_INVALID_HANDLE */);

  virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask);

  virtual int handle_timeout(const ACE_Time_Value &current_time, const void *act /* = 0 */);

  private:

  ACE_SOCK_Dgram m_gram;

  };

CUDPRequestHandler::CUDPRequestHandler(const ACE_INET_Addr &local_addr):m_gram(local_addr)
  {
  // set timer
  ACE_Time_Value initialDelay(3);
  ACE_Time_Value interval(5);
  ACE_Reactor::instance()->schedule_timer( this, 0, initialDelay, interval );
  }

  CUDPRequestHandler::~CUDPRequestHandler()
  {
  }

  ACE_HANDLE CUDPRequestHandler::get_handle(void) const 
  {
  return m_gram.get_handle();
  }

  int CUDPRequestHandler::handle_input( ACE_HANDLE fd )
  {
  char buf[BUFSIZ] = {0};
  ACE_INET_Addr from_addr;
  ssize_t nSize = m_gram.recv( buf, sizeof(buf), from_addr );
  if ( nSize != -1 )
  {
  m_clientAddr = from_addr;

  // get remote addr 
  ACE_TCHAR peer_name[128] = {0};
  if ( from_addr.addr_to_string( peer_name, 128 ) == 0 )
  {
  char szAddr[255] = {0};
  ACE_OS::sprintf( szAddr, ("%s udp data [%d bytes] from %s"), ACE_TEXT("%I%t"), ACE_OS::strlen(buf), peer_name );
  Log( szAddr );
  }

  // parse 
  char szBuff[MAX_PATH] = {0};
  sprintf( szBuff, ("[%s-%d bytes] is recv."), buf, ACE_OS::strlen(buf) );
  m_gram.send( szBuff, ACE_OS::strlen(szBuff), from_addr );


  }
  return 0;
  }

  int CUDPRequestHandler::handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask)
  {
  delete this;
  return 0;
  }

  int CUDPRequestHandler::handle_timeout(const ACE_Time_Value &current_time, const void *act )
  {
  time_t epoch = ((timespec_t)current_time).tv_sec;
  ACE_DEBUG((LM_INFO, ACE_TEXT("%I%t handle_timeout: %s\n"), ACE_OS::ctime(&epoch) ));
  return 0;
  }

==============================================================
ok,就这么点代码,出现问题的地方就在如下:
 int nResult = ACE_Reactor::instance()->run_reactor_event_loop(); // ?????????出现问题的地方?????
  if ( nResult == -1 )
  {
  return -1;
  }

当在主进程中创建线程时 :lpUdpServer->activate( THR_NEW_LWP|THR_JOINABLE, 4 );
会执行如下代码,但正常的话应该在 ACE_Reactor::instance()->run_reactor_event_loop();执行后阻塞,但在linux下,返回 -1。

这样导致客户端,发送的任何数据,int CUDPRequestHandler::handle_input( ACE_HANDLE fd ) 这个方法根本没有进来。

但以上的一切,在windows上全部正常。

非常郁闷,本人刚接触ace,希望高人指点,是因为我的使用方式上有问题,还是在linux上需要做特殊的处理?










[解决办法]
主线程里面定义handler
CUDPRequestHandler* lpUdpHandler = NULL;
在启动业务线程后,主线程即退出了

线程退出触发handle_close,进而 delete this。
可以在CUDPRequestHandler::~CUDPRequestHandler()里面增加日志打印看一下。



另外建议
int nResult = ACE_Reactor::instance()->run_reactor_event_loop();
放到主线程 进行事件循环调度。

大型网络程序应该是
udp server的svc主要应该是处理handler::handle_input收到消息后投递到本线程的数据。

你如果简单的处理,且压力不大的话你这设计也行。不过主线程别退出啊

最简单修改方式:
[1]
lpUdpServer->activate( THR_NEW_LWP|THR_JOINABLE, 4 );
后面增加
while(1){sleep(1);};
或者
[2]
把下面
int nResult = ACE_Reactor::instance()->run_reactor_event_loop();移过来确保主线程不退出。



试一下?

热点排行