王朝网络
分享
 
 
 

从我的角度理解ACE(一) -- ACE_Reactor

王朝other·作者佚名  2006-01-09
宽屏版  字体: |||超大  

大半年前买了本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;

uint32 m_start_tick;

uint32 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这些动态配置、模块合作的设计安排。如果有时间,我会再结合自己的经验教训,继续写下自己的心得体会。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有