因这边文章把复杂的东西说简单了,很喜欢这种风格,就把它贴上来了,对于新学者其实也很有研究价值
复杂的东西归于简单化思考,其实是很好理解的
来源:宇星软件园
大半年前买了本ACE的C++NPv2,翻了一下感觉满篇理论概念,没有看下去,然后这半年继续实现了些网络程序,前几天再次捧起这本书,先用两天时间囫囵吞枣、一目十行的粗览了一遍,结合自己之前的网络编程经验,感觉到一些共鸣,又再慢慢的进行仔细的阅读,写下自己的阅读体会。
篇(一)主要针对ACE_Reactor(反应器、反应堆)。
首先,先介绍一下我项目中自己写的一个网络编程库,对比一下,可以很好理解这个ACE_Reactor。
我的这个库,代码主要跨Linux/Win32平台,因为没有需要,没在其他平台测试过。这个库没有涉及UI部分,只是用来编写服务器端,或者Linux/Win32的控制台程序。先拿两个类来对比ACE_Reactor。
// 回调函数
typedef void (*pfn_sock_event_t)(socket_t* sock, int err, void* param);
// 非阻塞式socket
class socket_t
{
public:
...
// 创建时,加到socket_manager_t管理
bool create(...)
{
...
socket_manager_t::add(this, ...);
}
// attach时,加到socket_manager_t管理
bool attach(SOCKET s, ...)
{
...
socket_manager_t::add(this, ...);
}
// 关闭时从socket_manager_t移除
void close()
{
...
socket_manager_t::remove(this, ...);
}
// 设置回调函数
void set_callback(
pfn_sock_event_t on_recv = 0,
pfn_sock_event_t on_send = 0,
pfn_sock_event_t on_accept = 0,
pfn_sock_event_t on_close = 0,
pfn_sock_event_t on_connect = 0,
pfn_sock_event_t on_except = 0
);
...
protected:
SOCKET m_sock;
pfn_sock_event_t m_on_recv,
pfn_sock_event_t m_on_send,
pfn_sock_event_t m_on_accept,
pfn_sock_event_t m_on_close,
pfn_sock_event_t m_on_connect,
pfn_sock_event_t m_on_except
...
};
// socket_manager_t
// 拥有一个sockets数组或列表,统一一次性进行select()
class socket_manager_t
{
public:
...
static void add(socket_t* s, ...)
{
// 加入到m_socks
}
static void remove(socket_t* s, ...)
{
// 从m_socks移除
}
// 一次性对m_socks中所有的socket进行select()
static void poll()
{
int sck_cnt = m_socks.size();
...
for (i = 0; i < (sck - 1) / FD_SETSIZE + 1; ++i)
{
for (j = 0 ;j < FD_SETSIZE; ++j)
{
socket_t* sck = m_socks[idx];
if (...) FD_SET(sck->m_sock, fdWrite, ...);
if (...) FD_SET(sck->m_sock, fdRead, ...);
...
}
if (select(...) <= 0) continue;
for (j = 0 ;j < FD_SETSIZE; ++j)
{
socket_t* sck = m_socks[idx];
if (FD_ISSET(sck->m_sock, ...), ...)
if (sck->m_on_connect) sck->m_on_connect(sck, ...);
if (FD_ISSET(sck->m_sock, ...), ...)
if (sck->m_on_close) sck->m_on_close(sck, ...);
if (FD_ISSET(sck->m_sock, ...), ...)
if (sck->m_on_accept) sck->m_on_accept(sck, ...);
if (FD_ISSET(sck->m_sock, ...), ...)
if (sck->m_on_recv) sck->m_on_recv(sck, ...);
if (FD_ISSET(sck->m_sock, ...), ...)
if (sck->m_on_send) sck->m_on_send(sck, ...);
...
}
}
...
}
...
protected:
...
vector<socket_t*> m_socks;
};
最后,在main() 中,或者一个独立的线程中,循环执行socket_manager_t::poll() 如
void main()
{
...
while (!dead_event)
{
...
socket_manager_t::poll();
...
}
...
}
简单解说一下:
socket_t::create() 或者socket_t::attach() 时登记自己到socket_manager_t中,由socket_manager_t::poll()对所有的socket进行select(),触发及分派socket_t::on_recv()/socket_t::on_send()/socket_t::on_accept()等事件。
好,开始涉及ACE_Reactor。
功能上,可以等价的认为,上面的socket_manager_t就类似是ACE_Rector,主要作用就是事件触发中心、事件反应器、事件监控器、事件分派器等。
就像上面的socket一样,各种ACE_Event_Handler及其派生物类,都像socket_t::create()那样,有个向触发中心登记本身的动作,对于ACE_Event_Handler来说,是由程序员明显的调用ACE_Rector的register(...),而ACE_Event_Handler本身就有handle_input()/handle_output() 等虚拟函数,作为回调调用,就像上面的socket_t::on_recv/socket_t::on_send... 一样。加入到ACE_Rector中的各种ACE_Event_Handler,由ACE_Rector调用其他的事件查询/监听方式进行统一监控(比如socket的select(),Win32特有的WSAEventSelect() 等),当有事件在ACE_Event_Handler上发生时,调用它的handle_input()/handle_output()等虚拟函数。
ACE_Event_Handler进行ACE_Rector::register() 时,指定READ_MASK/WRITE_MASK等自己感兴趣的事件,handle_input()等回调被调用时返回适当的值,以指示ACE_Rector取消或继续监控自己。
至于ACE_Event_Handler还有个handle_except() 的虚拟回调函数,跟socket_t::on_except() 差不多。
ACE_Event_Handler还有个handle_timeout() 的虚拟回调,讲解一下。在我的程序中,曾经做过一个
// 回调函数
typedef void (*pfn_timer_event_t)(timer_t* tm, void* param);
class timer_t
{
...
timer_t(pfn_timer_event_t pfn, void* param, uint32 timeout_usecs)
{
m_start_tick = util_t::sys_tick();
timer_manager_t::add(this);
...
}
bool is_timeout(uint32 cur_tick)
{
return (cur_tick - m_start_tick >= m_timeout_usecs);
}
void process()
{
if (m_pfn) m_pfn(this, m_param);
}
protected;
pfn_timer_event_t m_pfn;
void* m_param;
uint
32 m
_start_tick;
uint
32 m
_timeout_usecs;
};
class timer_manager_t
{
...
void add(timer_t* tm)
{
// 加入到m_timers
...
}
void poll()
{
uint32 cur_tick = util_t::sys_tick();
for (int i = 0; i < m_timers.size(); ++i)
{
if (m_timers[i]->is_timeout(cur_tick))
{
// 超时,触发timer_t的事件
m_timers[i]->process();
...
}
...
}
}
vector<timer_t> m_timers;
};
在上面的那个main,或者一个线程中,比如
void main()
{
...
while (!dead_event)
{
...
socket_manager_t::poll();
timer_manager_t::poll();
...
}
...
}
而现在,ACE_Reactor只不过把这个timer_manager_t的功能一起集成进去而已。
最后声明一下,我还没具体看ACE的源代码,只是暂时从 <<ACEC++NPv2>> 的讲解上,字面上根据自己的经历大概理解一下ACE_Reactor,如果有什么错误,后期再改正。本文不打算成为什么学术指南,只作为个人经验参考。
后面的ACE_Server_Config/ACE_Module/ACE_Task等等,我粗览过一遍,而我的一个网络服务器程序,前期只是个login server的模块,后期因为业务需要,增加了多种server接口,以及增加了多服务器支持等,扩充维护的经历使我更能体会ACE这些动态配置、模块合作的设计安排。如果有时间,我会再结合自己的经验教训,继续写下自己的心得体会。