ACE - Reactor源码总结整理
ACE源码约10万行,是c++中非常大的一个网络编程代码库,包含了网络编程的边边角角。
ACE代码可以分三个层次:OS层、OO层和框架层:
- OS层主要是为了兼容各个平台,将网络底层API统一化,这一层用户不关心。
- OO层则是对一些常用的数据结构或方法进行OO封装,方便上层使用,包括socket方法,进程、线程和他们的同步机制等。
- 框架层实现了一些优秀的网络框架。
1 ACE_INET_Addr
|
类名 |
ACE_INET_Addr |
|
所在文件 |
INET_Addr.h |
|
功能 |
处理和存储IP、端口、协议类型的数据类,提供了一组操作这些数据的方法。 |
|
关键数据 |
/// Creates an ACE_INET_Addr from a @a port_number and ACE_INET_Addr (u_short port_number,
const char host_name[],
int address_family = AF_UNSPEC);
union
{
sockaddr_in in4_;
#if defined (ACE_HAS_IPV6)
sockaddr_in6 in6_;
#endif /* ACE_HAS_IPV6 */
} inet_addr_;
|
在构造时入参端口和IP地址完成赋值。
#define LISTEN_PORT 5010
#define SERVER_IP ACE_LOCALHOST
ACE_INET_Addr Server_Info(LISTEN_PORT,(char *)SERVER_IP);
2 ACE_SOCK_Acceptor
|
类名 |
ACE_SOCK_Acceptor |
|
所在文件 |
SOCK_Acceptor.h |
|
功能 |
接受器,被动建立连接,用于Socket Server。 |
|
关键数据 |
/** * Initialize a passive-mode BSD-style acceptor socket (no QoS). */ int open (const ACE_Addr &local_sap, int reuse_addr = , int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol = ); /** * Accept a new ACE_SOCK_Stream connection. A @a timeout of 0 */ int accept (ACE_SOCK_Stream &new_stream, ACE_Addr *remote_addr = , ACE_Time_Value *timeout = , bool restart = true, bool reset_new_handle = false) const; |
Open:创建socket,打开监听端口,绑定socket。完成socket、listen、bind操作。
|
文件:SOCK.cpp 代码行:141 - 146 |
this->set_handle (ACE_OS::socket (protocol_family, type, protocol, protocolinfo, g, flags)); |
|
文件:SOCK_Acceptor.cpp 代码行:279 - 282 |
else if (ACE_OS::bind (this->get_handle (), (sockaddr *) local_sap.get_addr (), local_sap.get_size ()) == -) error = ; |
|
文件:SOCK_Acceptor.cpp 代码行:284 - 291 |
if (error !=
|| ACE_OS::listen (this->get_handle (),
backlog) == -)
{
ACE_Errno_Guard g (errno); // Preserve across close() below.
error = ;
this->close ();
}
|
Accept:创建数据通道。完成accept操作。
|
文件:SOCK_Acceptor.cpp 代码行:134 - 136 |
new_stream.set_handle (ACE_OS::accept (this->get_handle (), addr, len_ptr)); |
3 ACE_SOCK_Stream
|
类名 |
ACE_SOCK_Stream |
|
所在文件 |
SOCK_Stream.h |
|
功能 |
传输数据的流,用于传输数据。 |
|
关键数据 |
/// Recv @a n bytes via Win32 @c ReadFile using overlapped I/O. ssize_t recv (void *buf, size_t n, ACE_OVERLAPPED *overlapped) const; /// Send an @a n byte buffer to the connected socket. ssize_t send (const void *buf, size_t n, int flags, const ACE_Time_Value *timeout = ) const; |
ACE_SOCK_Stream在ACE_SOCK_Acceptor执行accept时作为参数传入,accept把返回的IOhandle赋值给ACE_SOCK_Stream,ACE_SOCK_Stream利用IO进行recv和send数据收发。
Recv:接收accept连接上来的IO数据。
|
文件:SOCK_IO.cpp 代码行:143 - 145 |
ssize_t const result = ACE_OS::recvv (this->get_handle (), iovp, total_tuples); |
Send:向IO发送数据。
|
文件:SOCK_IO.cpp 代码行:103 - 105 |
ssize_t const result = ACE_OS::sendv (this->get_handle (), iovp, total_tuples); |
4 ACE_Task
|
类名 |
ACE_Task |
|
所在文件 |
Task_T.h |
|
功能 |
提供线程实例,也可以创建一组线程。包含一个消息队列。 |
|
关键数据 |
/// Insert message into the message queue. Note that @a timeout uses int putq (ACE_Message_Block *, ACE_Time_Value *timeout = ); /** * Extract the first message from the queue (blocking). */ int getq (ACE_Message_Block *&mb, ACE_Time_Value *timeout = ); // = Active object activation method. virtual int activate (long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, int n_threads = , int force_active = , long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -, ACE_Task_Base *task = , ACE_hthread_t thread_handles[] = , void *stack[] = , size_t stack_size[] = , ACE_thread_t thread_ids[] = , const char* thr_name[] = ); /// Run by a daemon thread to handle deferred processing. virtual int svc (void); /// Queue of messages on the ACE_Task.. ACE_Message_Queue<ACE_SYNCH_USE> *msg_queue_; |
Putq:将消息插入队列,ACE_Message_Queue<ACE_SYNCH_USE> *msg_queue_是ACE实现的一个消息队列。提供队列的存储和方法。
|
文件:Task_T.inl 代码行:29 |
this->msg_queue_->enqueue_tail (mb, tv); |
Getq:从消息队列中取一条数据记录。
|
文件:Task_T.inl 代码行:22 |
return this->msg_queue_->dequeue_head (mb, tv); |
Activate:创建并激活线程。
|
文件:Task.cpp 代码行:161 - 172 |
grp_spawned = this->thr_mgr_->spawn_n (n_threads, &ACE_Task_Base::svc_run, (void *) this, flags, priority, grp_id, task, thread_handles, stack, stack_size, thr_name); |
Svc:线程函数,需要继承类重写,创建时调用svc_run,入参为this当前类,以面向对象形式封装线程。
|
文件:Task.cpp 代码行:270 - 271 |
// Call the Task's svc() hook method. int const svc_status = t->svc (); |
5 ACE_Event_Handler
|
类名 |
ACE_Event_Handler |
|
所在文件 |
Event_Handler.h |
|
功能 |
事件接收器,与I/O绑定,当I/O产生不同事件时,执行ACE_Event_Handler的不同方法。 |
|
关键数据 |
/// Get the I/O handle. virtual ACE_HANDLE get_handle (void) const; /// Set the I/O handle. virtual void set_handle (ACE_HANDLE); /// Called when input events occur (e.g., connection or data). virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE); /// Called when output events are possible (e.g., when flow control /// abates or non-blocking connection completes). virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE); |
get_handle、set_handle:继承重写或调用它们去设置和获取I/O。
|
文件:Event_Handler.h 代码行:91 – 94 |
virtual ACE_HANDLE get_handle (void) const; virtual void set_handle (ACE_HANDLE); |
handle_input、handle_output:继承重写它们,当产生相应的I/O事件时将被执行。
|
文件:Event_Handler.h 代码行:91 – 94 |
virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE); virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE); |
6 ACE_Reactor
|
类名 |
ACE_Reactor |
|
所在文件 |
Reactor.h |
|
功能 |
Reactor框架,提供IO复用、消息循环和消息分发。 |
|
关键数据 |
int register_handler (ACE_Event_Handler *event_handler, ACE_HANDLE event_handle = ACE_INVALID_HANDLE); int remove_handler (ACE_HANDLE handle, ACE_Reactor_Mask masks); int run_reactor_event_loop (REACTOR_EVENT_HOOK = ); |
Reactor是I/O多路复用模式的一种,ACE提供了Reactor框架。
主要参与Reactor的对象有:
l 事件I/O,ACE_SOCK_Acceptor、ACE_SOCK_Stream的get_handle均提供对应I/O。
l 注册事件,继承于ACE_Event_Handler的对象。对象绑定了I/O,当产生I/O事件后将调用对象相对应的方法。
ACE_Reactor内部调用复杂,以下提供最后执行的关键代码。
register_handler:注册事件到Reactor,需要传入ACE_Event_Handler的派生类,即指定触发事件后将执行的函数,以及传入将被复用监听的I/O,I/O可以与ACE_Event_Handler绑定,也可以单独传入。Reactor将这两个信息绑定在handler_rep_容器内,并且将I/O以ADD形式添加到select_reactor_.wait_set_。
|
文件:Select_Reactor_T.cpp Select_Reactor_Base.cpp Select_Reactor_Base.cpp 代码行:993 249 265-268 |
return this->handler_rep_.bind (handle, event_handler, mask); |
this->event_handlers_[handle]= event_handler; |
this->select_reactor_.bit_ops (handle, mask, this->select_reactor_.wait_set_, ACE_Reactor::ADD_MASK); |
run_reactor_event_loop:消息循环主要进行两个操作,1.监听注册的I/O。2.当I/O产生事件后通知到绑定的ACE_Event_Handler具体执行函数。在监听部分使用select监听注册进去的I/O select_reactor_.wait_set_。通知时发送到指定的handle_input,handle_output等相应函数。
|
文件:Select_Reactor_T.cpp Select_Reactor_T.cpp Select_Reactor_Base.cpp 代码行: 1435 - 1441 1093 – 1100 737 - 746 |
int number_of_active_handles = this->wait_for_multiple_events (this->dispatch_set_, max_wait_time); result = this->dispatch (number_of_active_handles, this->dispatch_set_); |
dispatch_set.rd_mask_ = this->wait_set_.rd_mask_; dispatch_set.wr_mask_ = this->wait_set_.wr_mask_; dispatch_set.ex_mask_ = this->wait_set_.ex_mask_; number_of_active_handles = ACE_OS::select (width, dispatch_set.rd_mask_, dispatch_set.wr_mask_, dispatch_set.ex_mask_, this_timeout); |
ACE_HANDLE const read_handle =
this->notification_pipe_.read_handle ();
if (read_handle != ACE_INVALID_HANDLE
&& rd_mask.is_set (read_handle))
{
--number_of_active_handles;
rd_mask.clr_bit (read_handle);
return this->handle_input (read_handle);
}
|
ACE - Reactor源码总结整理的更多相关文章
- ACE Reactor 源码解析
http://blogs.readthedocs.org/ ACE的学习笔记,根据源码分析了Reactor模型的实现. 因为笔记编写技术限制,这里仅列出主要目录,如有可能可以抽空复制到该Blog中 ...
- ACE的源码划分
前几篇文章也提到过,ACE的所有源文件和头文件都杂乱堆在了ACE_wrappers/ace目录下.这样的代码组织方式给学习ACE带来了很大的困难,很多朋友在看到ace目录下庞大的代码的时候,几乎就失去 ...
- element-ui 组件源码分析整理笔记目录
element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...
- element-ui Carousel 走马灯源码分析整理笔记(十一)
Carousel 走马灯源码分析整理笔记,这篇写的不详细,后面有空补充 main.vue <template> <!--走马灯的最外层包裹div--> <div clas ...
- ACE - ACE_Task源码剖析及线程池实现
原文出自http://www.cnblogs.com/binchen-china,禁止转载. 上篇提到用Reactor模式,利用I/O复用,获得Socket数据并且实现I/O层单线程并发,和dispa ...
- 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生
[转].NET(C#):浅谈程序集清单资源和RESX资源 目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...
- laravel5源码讲解整理
来源:http://yuez.me/laravel-yuan-ma-jie-du/?utm_source=tuicool&utm_medium=referral 目录 入口文件 index.p ...
- Windows平台下载Android源码(整理)
Google官方下载源码使用的系统Ubuntu系统,不过现在我们需要在Windows系统中下载Android源码文件. 网站的地址是:https://android.googlesource.com/ ...
- element-ui button组件 radio组件源码分析整理笔记(一)
Button组件 button.vue <template> <button class="el-button" @click="handleClick ...
随机推荐
- 2015弱校联盟(2) - J. Usoperanto
J. Usoperanto Time Limit: 8000ms Memory Limit: 256000KB Usoperanto is an artificial spoken language ...
- JAVA基础知识之网络编程——-网络通信模型(IO模型)
<Unix网络编程:卷1>中介绍了5中I/O模型,JAVA作为运行在宿主机上的程序,底层也遵循这5中I/O模型规则.这5中I/O模型分别是: 阻塞式IO 非阻塞式IO I/O复用 信号驱动 ...
- async和await浅析
要理解async和await的用法,首先要了解Task相关知识,这里不做说明,因为这不是本文的重点. 如果你已经对Task很了解,那么如何使用async和await,在此主要总结了以下三点: 只有在a ...
- Android 自动化测试 Emmagee
Emmagee 是一个性能测试小工具 用来监控指定被测应用在使用过程中占用机器的CPU, 内存,流量资源的性能小工具 阅读目录 Emmagee 介绍 Emmagee是网易杭州研究院QA团队开发的一个简 ...
- 关于sifari兼容性的一个问题
输入框 一个很基础的控件 结果出现了兼容性问题 在chrome ie android上页面正常 结果在Safari和IOS系统里面输入框无法输入, 点击后边框有高亮效果但是无法输入文本,问题代码如下: ...
- socket(一)
相关链接: http://my.oschina.net/u/1378445/blog/340206?p=2&temp=1469158886336#blog-comments-list http ...
- Linux文件管理相关命令
Linux文件管理相关命令 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在了解了Linux文件管理背景知识之后, 我们可以 ...
- CSS布局基础之二认识Viewport
什么是viewport viewport,等同于浏览器窗口. 功能:约束你网站中最顶级包含块(containing block)元素html标签. 什么是包含块(containing block)?下 ...
- Android NDK开发入门实例
AndroidNDK是能使Android应用开发者把从c/c++编译而来的本地代码嵌入到应用包中的一系列工具的组合. 注意: AndroidNDK只能用于Android1.5及以上版本中. I. An ...
- HDU-4534 郑厂长系列故事——新闻净化 AC自动机+DP
题意:给定一些单词,这些单词必须要是一个目标串的子串,同时给定一些串,这些串不能够出现在目标串中,其余一些串只会带来不同附加值.现在问满足前两者的情况下,要求附加值最大.数据给定一个原始串,现在要求在 ...