欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 编程资源 > 编程问答 >内容正文

编程问答

网络编程模型 / reactor -凯发k8官方网

发布时间:2024/10/14 编程问答 32 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 网络编程模型 / reactor 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

之前一直不理解 reactor 模型的含义,后来在知乎上看见了一个 demo,再结合文字终于理解什么是 reactor 模型了,这里分享给大家。

一、介绍

网络编程模型通常有如下几种:reactorproactorasynchronous completion token and acceptor-connector。本文主要对最主流的 reactor模型进行介绍。

通常网络编程模型处理的主要流程如下

initiate => receive => demultiplex => dispatch => process events

i/o 多路复用可以用作并发事件驱动(event-driven)程序的基础,即整个事件驱动模型是一个状态机,包含了状态(state), 输入事件(input-event), 状态转移(transition), 状态转移即状态到输入事件的一组映射。通过 i/o 多路复用的技术检测事件的发生,并根据具体的事件(通常为读写),进行不同的操作,即状态转移。

reactor 模式是一种典型的事件驱动的编程模型,reactor 逆置了程序处理的流程,其基本的思想即为 hollywood principle — 'don't call us, we'll call you'。

普通的函数处理机制为:调用某函数 -> 函数执行, 主程序等待阻塞 -> 函数将结果返回给主程序 -> 主程序继续执行。

reactor 事件处理机制为:主程序将事件以及对应事件处理的方法在 reactor 上进行注册,如果相应的事件发生,reactor 将会主动调用事件注册的接口,即 回调函数。libevent 封装了 epoll 并注册相应的事件(i/o读写,时间事件,信号事件)以及回调函数,实现的事件驱动的框架。

二、架构

1、事件(事件源)

linux 上为文件描述符,handler 即为注册在特定事件上的程序,事件发生通常在 linux 下为 i/o 事件,由操作系统触发。

2、reactor (反应器)

事件管理的接口,内部使用 event demultiplexer 注册、注销事件;并运行事件循环,当有事件进入"就绪"状态时,调用注册事件的回调函数处理事件。

class reactor { public:int register_handler(eventhandler *phandler, int event);int remove_handler(eventhandler *phandler, int event);void handle_events(timeval *ptv); }

3、event demultiplexer(事件多路分发机制)

通常是由操作系统提供的 i/o 多路复用的机制,例如 select,epoll。程序首先将 handler(事件源)以及对应的事件注册到 event demultiplexer 上;当有事件到达时,event demultiplexer 就会发出通知,通知 reactor 调用事件处理程序进行处理。

4、event handler(事件处理程序)

事件处理程序提供了一组接口,在 reactor 相应的事件发生时调用,执行相应的事件处理,通常会绑定一个有效的 handler 。

class event_handler { public:// events maybe read/write/timeout/close .etcvirtual void handle_events(int events) = 0;virtual handle get_handle() = 0; }

三、实现

#include #include #include #include #include typedef std::string eventtype; class myeventdemultiplexer { public:static const int no_flags = 0;static const int block_indefinitely = -1;static const int max_events = 5;myeventdemultiplexer(){filedescriptor = epoll_create1(no_flags);event.data.fd = stdin_fileno;//设置epoll event 为 epollin (对应文件描述符可读), epollpri (对应文件描述符有紧急事件可读)event.events = epollin | epollpri;}~myeventdemultiplexer(){close(filedescriptor);}int wait(){return epoll_wait(filedescriptor, events.data(), max_events, block_indefinitely);}int control(){return epoll_ctl(filedescriptor, epoll_ctl_add, stdin_fileno, &event);}private:int filedescriptor;struct epoll_event event;std::array events{}; };class myeventhandler { public:int handle_event(eventtype et){std::cout << "event handler: " << et << std::endl;return 0;} };class reactor { public:reactor(){m_event_demultiplexer.control();}void addhandler(std::string event, myeventhandler callback){handlers.emplace(std::move(event), std::move(callback));}void run(){while (true){int numberofevents = wait();for (int i = 0; i < numberofevents; i){std::string input;std::getline(std::cin, input);try{// 根据的具体的事件去找对应的handler,并执行相应的操作handlers.at(input).handle_event(eventtype(input));}catch (const std::out_of_range &e){std::cout << "no handler for " << input << std::endl;}}}}private:std::unordered_map handlers{};myeventdemultiplexer m_event_demultiplexer;int wait(){int numberofevents = m_event_demultiplexer.wait();return numberofevents;} };int main() {reactor reactor;reactor.addhandler("a", myeventhandler{});reactor.addhandler("b", myeventhandler{});reactor.run(); }

结果:

a event handler: a b event handler: b c no handler for c

转载于:https://zhuanlan.zhihu.com/p/93612337

(saw:game over!)

 

总结

以上是凯发k8官方网为你收集整理的网络编程模型 / reactor的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

网站地图