ACE高效PROACTOR编程框架一ClientHandle

简介:

1、WIN32下面用proactor可以达到几乎RAW IOCP的效率,由于封装关系,应该是差那么一点。

客户端处理类的常规写法:
//处理客户端连接消息
class ClientHandler : public ACE_Service_Handler
{
public:
 /**构造函数
  *
  *
  */
 ClientHandler(unsigned int client_recv_buf_size=SERVER_CLIENT_RECEIVE_BUF_SIZE)
  :_read_msg_block(client_recv_buf_size),_io_count(0)
 {
 }


 ~ClientHandler(){}

 /**
  *初始化,因为可能要用到ClientHandler内存池,而这个池又不一定要用NEW
  */
 void init();

 /**清理函数,因为可能要用到内存池
  *
  */
 void fini();

//检查是否超时的函数

 void check_time_out(time_t cur_time);

public:

 /**客户端连接服务器成功后调用
  *
  * \param handle 套接字句柄
  * \param &message_block 第一次读到的数据(未用)
  */

//由Acceptor来调用!!!
 virtual void open (ACE_HANDLE handle,ACE_Message_Block &message_block);

 /**处理网络读操作结束消息
  *
  * \param &result 读操作结果
  */
 virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);


 /**处理网络写操作结束消息
  *
  * \param &result 写操作结果
  */
 virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);

private:

//**生成一个网络读请求
  *
  * \param void 
  * \return 0-成功,-1失败
  */
 int  initiate_read_stream  (void);

 /**生成一个写请求
  *
  * \param mb 待发送的数据
  * \param nBytes 待发送数据大小
  * \return 0-成功,-1失败
  */
 int  initiate_write_stream (ACE_Message_Block & mb, size_t nBytes );
 
 /**
  *
  * \return 检查是否可以删除,用的是一个引用计数。每一个外出IO的时候+1,每一个IO成功后-1
  */
 int check_destroy();
 
 //异步读
 ACE_Asynch_Read_Stream _rs;

 //异步写
 ACE_Asynch_Write_Stream _ws;

 //接收缓冲区只要一个就够了,因为压根就没想过要多读,我直到现在也不是很清楚为什么要多读,多读的话要考虑很多问题
 ACE_Message_Block _read_msg_block;

 //套接字句柄,这个可以不要了,因为基类就有个HANDLER在里面的。
 //ACE_HANDLE _handle;

 //一个锁,客户端反正有东东要锁的,注意,要用ACE_Recursive_Thread_Mutex而不是用ACE_Thread_Mutex,这里面是可以重入的,而且在WIN32下是直接的EnterCriticalSection,可以达到很高的效率
 ACE_Recursive_Thread_Mutex _lock;
 
 //在外IO数量,其实就是引用计数啦,没啥的。为0的时候就把这个东东关掉啦。
 long _io_count;

//检查超时用的,过段时间没东东就CLOSE他了。

 time_t _last_net_io;

private:

//本来想用另外一种模型的,只用1个或者2个外出读,后来想想,反正一般内存都是足够的,就不管了。

 //ACE_Message_Block _send_msg_blocks[2];

 //ACE_Message_Block &_sending_msg_block;

 //ACE_Message_Block &_idle_msg_block;

private:
 
public:
//TODO:move to prriva and use friend class!!!

//只是为了效率更高,不用STL的LIST是因为到现在我没有可用的Node_Allocator,所以效率上会有问题。
 ClientHandler *_next;

 ClientHandler *next(){return _next;}

 void next(ClientHandler *obj){_next=obj;}

};


//这是具体实现,有些地方比较乱,懒得管了,锁的有些地方不对。懒得改了,反正在出错或者有瓶颈的时候再做也不迟。

void ClientHandler::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
{
 _last_net_io=ACE_OS::time(NULL);
 int byterecved=result.bytes_transferred ();
 if ( (result.success ()) && (byterecved != 0))
 {
  //ACE_DEBUG ((LM_DEBUG,  "Receiver completed:%d\n",byterecved));

//处理完数据
  if(handle_received_data()==true)
  {
   //ACE_DEBUG ((LM_DEBUG,  "go on reading...\n"));

//把东东推到头部,处理粘包
   _read_msg_block.crunch();
   initiate_read_stream();
  }
 }

//这个地方不想用ACE_Atom_op,因为反正要有一个锁,而且一般都会用锁,不管了。假如不在意的话,应该直接用ACE_Atom_Op以达到最好的效率

 {
  ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);
  _io_count--;
 }
 check_destroy ();
}

void ClientHandler::init()
{

//初始化数据,并不在构造函数里做。
 _last_net_io=ACE_OS::time(NULL);
 _read_msg_block.rd_ptr(_read_msg_block.base());
 _read_msg_block.wr_ptr(_read_msg_block.base());
 this->handle(ACE_INVALID_HANDLE);
}

bool ClientHandler::handle_received_data()
{

...........自己处理
 return true;
}


//==================================================================
void ClientHandler::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
{
 //发送成功,RELEASE掉
 //这个不可能有多个RELEASE,直接XX掉
 //result.message_block ().release ();
 MsgBlockManager::get_instance().release_msg_block(&result.message_block());

 {
  ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);
  _io_count--;
 }
 check_destroy ();
}

//bool ClientHandler::destroy () 
//{
// FUNC_ENTER;
// ClientManager::get_instance().release_client_handle(this);
// FUNC_LEAVE;
// return false ;
//}


int  ClientHandler::initiate_read_stream  (void)
{
 ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);

//考虑到粘包的呀
 if (_rs.read (_read_msg_block, _read_msg_block.space()) == -1)
 {
  ACE_ERROR_RETURN ((LM_ERROR,"%p\n","ACE_Asynch_Read_Stream::read"),-1);
 }
 _io_count++;
 return 0;
}

/**生成一个写请求
*
* \param mb 待发送的数据
* \param nBytes 待发送数据大小
* \return 0-成功,-1失败
*/
int  ClientHandler::initiate_write_stream (ACE_Message_Block & mb, size_t nBytes )
{
 ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);
 if (_ws.write (mb , nBytes ) == -1)
 {
  mb.release ();
  ACE_ERROR_RETURN((LM_ERROR,"%p\n","ACE_Asynch_Write_File::write"),-1);
 }
 _io_count++;
 return 0;
}

void ClientHandler::open (ACE_HANDLE handle,ACE_Message_Block &message_block)
{
 //FUNC_ENTER;
 _last_net_io=ACE_OS::time(NULL);
 _io_count=0;
 if(_ws.open(*this,this->handle())==-1)
 {
  ACE_ERROR ((LM_ERROR,"%p\n","ACE_Asynch_Write_Stream::open"));
 }
 else if (_rs.open (*this, this->handle()) == -1)
 {
  ACE_ERROR ((LM_ERROR,"%p\n","ACE_Asynch_Read_Stream::open"));
 }
 else
 {
  initiate_read_stream ();
 }

 check_destroy();
 //FUNC_LEAVE;
}

void ClientHandler::fini()
{
}

void ClientHandler::check_time_out(time_t cur_time)
{
 //ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);
 //ACE_DEBUG((LM_DEBUG,"cur_time is %u,last io is %u\n",cur_time,_last_net_io));

 //检测是否已经为0了
 if(this->handle()==ACE_INVALID_HANDLE)
  return;
 if(cur_time-_last_net_io>CLIENT_TIME_OUT_SECONDS)
 {
  ACE_OS::shutdown(this->handle(),SD_BOTH);
  ACE_OS::closesocket(this->handle());
  this->handle(ACE_INVALID_HANDLE);
 }
}

int ClientHandler::check_destroy()
{
 {
  ACE_Guard<ACE_Recursive_Thread_Mutex> locker (_lock);
  if (_io_count> 0)
   return 1;
 }
 ACE_OS::shutdown(this->handle(),SD_BOTH);
 ACE_OS::closesocket(this->handle());
 this->handle(ACE_INVALID_HANDLE);

//这个地方给内存池吧。
 ClientManager::get_instance().release_client_handle(this);
 //delete this;
 return 0;
}

目录
相关文章
|
1月前
|
数据库 Android开发 开发者
构建高性能微服务架构:从理论到实践构建高效Android应用:探究Kotlin协程的优势
【2月更文挑战第16天】 在当今快速迭代和竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性和独立部署能力而受到企业的青睐。本文将深入探讨如何构建一个高性能的微服务系统,涵盖从理论基础到具体实现的各个方面。我们将重点讨论服务拆分策略、通信机制、数据一致性以及性能优化等关键主题,为读者提供一个清晰、实用的指南,以便在复杂多变的业务环境中构建和维护健壮的微服务体系结构。 【2月更文挑战第16天】 在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着技术的不断进步,Kotlin作为一种现代编程语言,在Android开发中被广泛采用,尤其是其协程特性为异步编程带来了革命性的改进。本文旨在深入
240 5
|
21天前
|
网络协议 安全 Java
Java网络编程实战:构建高效稳定的网络通信
【4月更文挑战第2天】Java网络编程涉及Socket编程,基于TCP(可靠,面向连接)和UDP(不可靠,无连接)协议。Socket类和ServerSocket类用于TCP,而DatagramSocket和DatagramPacket处理UDP。高效通信涉及线程管理、选择合适的IO模型(如NIO)、利用缓冲区及确保网络安全,如使用SSL/TLS。适用于Web服务器、文件传输等场景。
Java网络编程实战:构建高效稳定的网络通信
|
28天前
|
消息中间件 存储 监控
【ZeroMQ的SUB视角】深入探讨订阅者模式、C++编程实践与底层机制
【ZeroMQ的SUB视角】深入探讨订阅者模式、C++编程实践与底层机制
106 1
|
9月前
|
负载均衡 Linux UED
开启极速之旅:了解Linux网络设计中的Reactor模型与百万级并发实践
本文将带您进入Linux网络设计的奇妙世界,着重介绍了Reactor模型和百万级并发的实践经验。在快节奏的现代互联网环境下,高性能的网络应用对于提供卓越的用户体验至关重要。通过深入探索Reactor模型,我们将揭示其在构建高并发应用中的关键作用。从基本概念到实际应用,您将了解到如何通过Reactor模型优化网络通信,实现快速响应和高吞吐量。此外,我们将分享一些实践中的经验和技巧,包括事件驱动编程、多线程与多进程处理、负载均衡等方面,以帮助您更好地应对百万级并发挑战。
58 0
开启极速之旅:了解Linux网络设计中的Reactor模型与百万级并发实践
事件驱动式编程
事件驱动式编程
119 1
|
编解码 数据库 开发者
如何用 keda 实现事件驱动的弹性|学习笔记
快速学习如何用 keda 实现事件驱动的弹性
159 0
如何用 keda 实现事件驱动的弹性|学习笔记
|
缓存 前端开发 网络协议
重新思考5G的基础知识 | 带你读《5G系统关键技术详解》之六
全球移动数据流量从 2015 年到 2020 年将继续快速增长。同时,第 5G 需要加强电信基础设施,提供新的信息服务,以支持农业、医药、金融、交通运输、制 造业、教育等各个行业领域的垂直应用。因此,5G 需要创新的解决方案,以满足移动互联 网和物联网(IoT,Internet of Things)对用户体验数据速率提升、延迟降低、连接密度和地 区容量密度增强、移动性增强、频谱效率和能效等方面的新需求。
|
数据采集 网络协议 应用服务中间件
多线程、事件驱动与推荐引擎框架选型
  事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。多线程是另一种常用编程范式,并且更容易理解。   高性能通用型C++网络框架 Nebula 是基于事件驱动的多进程网络框架(适用于即时通讯、数据采集、实时计算、消息推送等应用场景),已有即时通讯、埋点数据采集及实时分析的生产应用案例。
2361 0
|
Web App开发 XML 缓存
基于协程的编程方式在移动端研发的思考及最佳实践
超级App的性能和代码痛点 在iOS开发中线程使用特别方便,但是多线程使用不当引发的崩溃问题很多 多线程访问引发野指针问题 多线程访问引发容器类崩溃问题 多线程访问引发过渡释放问题 以手机淘宝为例,整个生命周期大量使用线程,多线程使用不当引发的崩溃问题占比达到了60%以上** 为了解决多线程.
1920 0
|
存储 人工智能 算法
为了提升DL模型性能,阿里工程师打造了流式编程框架
随着深度学习在全球的风靡,算法模型层出不穷,如何将算法落地到生产环境中成为了热门研究领域。目前提高算法运行效率的主要聚焦点为优化模型结构、将权重数据进行量化,图优化等方面,然而,它们或多或少都会对模型精度带来一定的损失,不能做到完全的无损优化。
3156 0

热门文章

最新文章