基於ACE的網絡服務端通訊編程

完成了基本的通訊功能

測試報告如下:

昨天準備11臺   只有7臺機子可以運行  每個開了10個
大部分  都好的   有1臺開10個的時候出錯   還有1臺早上看的時候10個都出錯

 


根據上面的圖顯示結果來看是由於服務端先關閉,客戶端發送數據失敗導致。

 

源代碼如下:

class ClientAcceptor : public ACE_Event_Handler
{
public:
 ClientAcceptor(void);
 virtual ~ClientAcceptor(void);
 //
 int open(const ACE_INET_Addr &listen_addr);
 //得到當前句柄的I/O句柄
 virtual ACE_HANDLE get_handle(void) const
 {
  return this->acceptor_.get_handle();
 }
 //當一個連接準備接受的時候調用這個函數
 virtual int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE);

 //當這個句柄從ACE_Reactor中移除的時候調用這個函數
 virtual int handle_close(ACE_HANDLE handle,ACE_Reactor_Mask close_mask);

 

protected:
 ACE_SOCK_Acceptor acceptor_;

};
 

 

#i nclude "StdAfx.h"
#i nclude "./lientacceptor.h"

ClientAcceptor::ClientAcceptor(void)
{
}

ClientAcceptor::~ClientAcceptor(void)
{
 this->handle_close(ACE_INVALID_HANDLE,0);
}


int ClientAcceptor::open(const ACE_INET_Addr &listen_addr)
{
 if(this->acceptor_.open(listen_addr,1) == -1)
 {
  ACE_ERROR_RETURN((LM_ERROR,ACE_TEXT("%p/n"),ACE_TEXT("acceptor.open")),-1);

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


int ClientAcceptor::handle_input(ACE_HANDLE)
{
 ClientService *client;
 ACE_NEW_RETURN(client,ClientService,-1);
 auto_ptr<ClientService> p (client);

 if(this->acceptor_.accept(client->peer()) == -1)
 {
  ACE_ERROR_RETURN((LM_ERROR,ACE_TEXT("(%P|%t) %p/n"),ACE_TEXT("Failed to accept"),ACE_TEXT("client connection")),-1);

 }
 
 p.release();
 client->reactor(this->reactor());
 if(client->open() == -1)
 {
  client->handle_close(ACE_INVALID_HANDLE,0);

 }
 return 0;

}

int ClientAcceptor::handle_close(ACE_HANDLE,ACE_Reactor_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;
}

 

class ClientService : public ACE_Event_Handler
{
public:
 ClientService(void);
 virtual ~ClientService(void);
 
 ACE_SOCK_Stream &peer(void) {return this->sock_;}

 int open(void);

 //得到當前句柄的I/O句柄
 virtual ACE_HANDLE get_handle(void) const
 {
  return this->sock_.get_handle();
 }
 //當客戶端出現一個input
 virtual int handle_input(ACE_HANDLE fd = ACE_INVALID_HANDLE);

 //當發生一個output的時候
 virtual int handle_output(ACE_HANDLE fd = ACE_INVALID_HANDLE);

 //當從ACE_Reactor移除一個句柄的時候
 virtual int handle_close(ACE_HANDLE handle,ACE_Reactor_Mask close_mask);

protected:
 ACE_SOCK_Stream sock_;
 ACE_Message_Queue<ACE_NULL_SYNCH> output_queue_;
};

 

 

#i nclude "StdAfx.h"
#i nclude "./lientservice.h"

ClientService::ClientService(void)
{
}

ClientService::~ClientService(void)
{
}


int ClientService::handle_input(ACE_HANDLE)
{
 const size_t INPUT_SIZE = 4096;
 char buffer[INPUT_SIZE];
 ssize_t recv_cnt,send_cnt;

 if((recv_cnt = this->sock_.recv(buffer,sizeof(buffer))) <= 0)
 {
  ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%P|%t) Connection closed/n")));
  return -1;
 }
 
 /*
  * 在這裏加入數據包處理函數
  
  */
 send_cnt = this->sock_.send(buffer,ACE_static_cast(size_t,recv_cnt));

 if(send_cnt == recv_cnt)
 {
  return 0;
 }

 if(send_cnt == -1 && ACE_OS::last_error() != EWOULDBLOCK)
 {
  ACE_ERROR_RETURN((LM_ERROR,ACE_TEXT("(%P|%t) %p/n"),ACE_TEXT("send")),0);

 }

 if(send_cnt == -1)
  send_cnt = 0;

 ACE_Message_Block *mb;
 size_t remaining = ACE_static_cast(size_t,(recv_cnt - send_cnt));
 ACE_NEW_RETURN(mb,ACE_Message_Block(&buffer[send_cnt],remaining),-1);
 int output_off = this->output_queue_.is_empty();
 ACE_Time_Value nowait(ACE_OS::gettimeofday());
 if(this->output_queue_.enqueue_tail(mb,&nowait) == -1)
 {
  ACE_ERROR((LM_ERROR,ACE_TEXT("(%P|%t) %p; discarding data/n"),ACE_TEXT("enqueue failed")));
  mb->release();
  return 0;
 }
 
 if(output_off)
 {
  return this->reactor()->register_handler(this,ACE_Event_Handler::WRITE_MASK);
  
 }
 return 0;
}


int ClientService::handle_output(ACE_HANDLE)
{
 ACE_Message_Block *mb;
 ACE_Time_Value nowait(ACE_OS::gettimeofday());
 while( 0 == this->output_queue_.dequeue_head(mb,&nowait))
 {
  ssize_t send_cnt = this->sock_.send(mb->rd_ptr(),mb->length());
  if(send_cnt == -1)
  {
   ACE_ERROR((LM_ERROR,ACE_TEXT("(%P|%t) %p/n"),ACE_TEXT("send")));
  }
  else
  {
   mb->rd_ptr(ACE_static_cast(size_t,send_cnt));
  }
  if(mb->length() > 0)
  {
   this->output_queue_.enqueue_head(mb);
   break;
  }
  mb->release();
 }
 return(this->output_queue_.is_empty())? -1 : 0;
 
}


int ClientService::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();
 this->output_queue_.flush();
 delete this;
 return 0;
}

int ClientService::open(void)
{
 ACE_TCHAR peer_name[MAXHOSTNAMELEN];
 ACE_INET_Addr peer_addr;
 if(this->sock_.get_remote_addr(peer_addr) == 0 && peer_addr.addr_to_string(peer_name,MAXHOSTNAMELEN) == 0)
 {
  ACE_DEBUG((LM_DEBUG,ACE_TEXT("(%P|%t) Connection from %s/n"),peer_name));

 }
 return this->reactor()->register_handler(this,ACE_Event_Handler::READ_MASK);
}

  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章