这是最近在学习ACE所记下的一点笔记,ACE十分庞大,传闻学之者生,用之者死,也说明坑多且繁杂。听前辈说在设计思路上无论是重量级还是如libevent这种轻量级的网络库,都是大同小异的,初学ACE首先要知道这些API。目前后台框架是在ACE框架之上的封装。
ACE源码约10万行,是c++中非常大的一个网络编程代码库,包含了网络编程的边边角角。
ACE代码可以分三个层次:OS层、OO层和框架层:
- OS层主要是为了兼容各个平台,将网络底层API统一化,这一层用户不关心。
- OO层则是对一些常用的数据结构或方法进行OO封装,方便上层使用,包括socket方法,进程、线程和他们的同步机制等。
- 框架层实现了一些优秀的网络框架。
1.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, constchar 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);
1.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 =0, int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol =0);
/** * Accept a new ACE_SOCK_Stream connection. A @a timeout of 0 */ int accept (ACE_SOCK_Stream &new_stream, ACE_Addr *remote_addr =0, ACE_Time_Value *timeout =0, bool restart =true, bool reset_new_handle =false)const; |
Open:创建socket,打开监听端口,绑定socket。完成socket、listen、bind操作。
代码行:141 - 146 |
this->set_handle (ACE_OS::socket(protocol_family, type, protocol, protocolinfo, g, flags)); |
文件:SOCK_Acceptor.cpp 代码行:279 - 282 |
elseif(ACE_OS::bind(this->get_handle (), (sockaddr *) local_sap.get_addr (), local_sap.get_size ())==-1) error =1; |
文件:SOCK_Acceptor.cpp 代码行:284 - 291 |
if(error !=0 || ACE_OS::listen(this->get_handle (), backlog)==-1) { ACE_Errno_Guard g (errno); // Preserve across close() below. error =1; this->close (); } |
Accept:创建数据通道。完成accept操作。
文件:SOCK_Acceptor.cpp 代码行:134 - 136 |
new_stream.set_handle (ACE_OS::accept(this->get_handle (), addr, len_ptr)); |
1.3ACE_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 (constvoid*buf, size_t n, int flags, const ACE_Time_Value *timeout =0)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_tconst result = ACE_OS::recvv(this->get_handle (), iovp, total_tuples); |
Send:向IO发送数据。
文件:SOCK_IO.cpp 代码行:103 - 105 |
ssize_tconst result = ACE_OS::sendv(this->get_handle (), iovp, total_tuples); |
1.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 =0);
/** * Extract the first message from the queue (blocking). */ int getq (ACE_Message_Block *&mb, ACE_Time_Value *timeout =0);
// = Active object activation method. virtualint activate (long flags = THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, int n_threads =1, int force_active =0, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id =-1, ACE_Task_Base *task =0, ACE_hthread_t thread_handles[]=0, void*stack[]=0, size_t stack_size[]=0, ACE_thread_t thread_ids[]=0, constchar* thr_name[]=0);
/// Run by a daemon thread to handle deferred processing. virtualint 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 |
returnthis->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. intconst svc_status = t->svc(); |
1.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. virtualvoid set_handle (ACE_HANDLE);
/// Called when input events occur (e.g., connection or data). virtualint 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). virtualint 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;
virtualvoid set_handle (ACE_HANDLE); |
handle_input、handle_output:继承重写它们,当产生相应的I/O事件时将被执行。
文件:Event_Handler.h 代码行:91 – 94 |
virtualint handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
virtualint handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE); |
1.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 =0); |
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 |
returnthis->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); returnthis->handle_input(read_handle); }
|