iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++中Reactor怎么实现
  • 433
分享到

C++中Reactor怎么实现

2023-07-02 14:07:19 433人浏览 薄情痞子
摘要

这篇文章主要介绍“c++中Reactor怎么实现”,在日常操作中,相信很多人在C++中Reactor怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中Reactor怎么实现”的疑惑有所帮助!接下来

这篇文章主要介绍“c++Reactor怎么实现”,在日常操作中,相信很多人在C++中Reactor怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中Reactor怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、Reactor介绍

reactor设计模式是event-driven architecture的一种实现方式,处理多个客户端并发的向服务端请求服务的场景。每种服务在服务端可能由多个方法组成。reactor会解耦并发请求的服务并分发给对应的事件处理器来处理。

中心思想是将所有要处理的I/o事件注册到一个中心I/o多路复用器上,同时主线程/进程阻塞在多路复用器上;一旦有I/o事件到来或是准备就绪(文件描述符或Socket可读、写),多路复用器返回并将事先注册的相应l/o事件分发到对应的处理器中。

处理机制为:主程序将事件以及对应事件处理的方法在Reactor上进行注册, 如果相应的事件发生,Reactor将会主动调用事件注册的接口,即 回调函数.

二、代码实现

前提准备:1单例模式:单例模式(Singleton Pattern,也称为单件模式),使用最广泛的设计模式之一。其意图是保证一个类(结构体)仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
2.回调函数:把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。

对epoll反应堆中结构体定义

struct nitem { // fdint fd;//要监听的文件描述符int status;//是否在监听:1->在红黑树上(监听),0->不在(不监听)int events;//对应的监听事件,EPOLLIN和EPOLLOUT(不同的事件,走不同的回调函数)void *arg;//指向自己结构体指针#if 0NCALLBACK callback;#elseNCALLBACK *readcb;   // epollinNCALLBACK *writecb;  // epolloutNCALLBACK *acceptcb; // epollin#endifunsigned char sbuffer[BUFFER_LENGTH]; //int slength;unsigned char rbuffer[BUFFER_LENGTH];int rlength;};struct itemblock {struct itemblock *next;struct nitem *items;};struct reactor {int epfd;struct itemblock *head; };

单例模式,创建reactor的一个实例

struct reactor *instance = NULL;int init_reactor(struct reactor *r) {if (r == NULL) return -1;int epfd = epoll_create(1); //int sizer->epfd = epfd;// fd --> itemr->head = (struct itemblock*)malloc(sizeof(struct itemblock));if (r->head == NULL) {close(epfd);return -2;} memset(r->head, 0, sizeof(struct itemblock));r->head->items = (struct nitem *)malloc(MAX_EPOLL_EVENT * sizeof(struct nitem));if (r->head->items == NULL) {free(r->head);close(epfd);return -2;}memset(r->head->items, 0, (MAX_EPOLL_EVENT * sizeof(struct nitem)));r->head->next = NULL;return 0;}struct reactor *getInstance(void) { //singletonif (instance == NULL) {instance = (struct reactor *)malloc(sizeof(struct reactor));if (instance == NULL) return NULL;memset(instance, 0, sizeof(struct reactor));if (0 > init_reactor(instance)) {free(instance);return NULL;}}return instance;}

事件注册

int nreactor_set_event(int fd, NCALLBACK cb, int event, void *arg) {struct reactor *r = getInstance();struct epoll_event ev = {0};//1if (event == READ_CB) {r->head->items[fd].fd = fd;r->head->items[fd].readcb = cb;r->head->items[fd].arg = arg;ev.events = EPOLLIN;}//2else if (event == WRITE_CB) {r->head->items[fd].fd = fd;r->head->items[fd].writecb = cb;r->head->items[fd].arg = arg;ev.events = EPOLLOUT;} //3else if (event == ACCEPT_CB) {r->head->items[fd].fd = fd;r->head->items[fd].acceptcb = cb;//回调函数r->head->items[fd].arg = arg;ev.events = EPOLLIN;}ev.data.ptr = &r->head->items[fd];if (r->head->items[fd].events == NOSET_CB) {if (epoll_ctl(r->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {printf("epoll_ctl EPOLL_CTL_ADD failed, %d\n", errno);return -1;}r->head->items[fd].events = event;} else if (r->head->items[fd].events != event) {if (epoll_ctl(r->epfd, EPOLL_CTL_MOD, fd, &ev) < 0) {printf("epoll_ctl EPOLL_CTL_MOD failed\n");return -1;}r->head->items[fd].events = event;}return 0;}

回调函数书写

int write_callback(int fd, int event, void *arg) {struct reactor *R = getInstance();unsigned char *sbuffer = R->head->items[fd].sbuffer;int length = R->head->items[fd].slength;int ret = send(fd, sbuffer, length, 0);if (ret < length) {nreactor_set_event(fd, write_callback, WRITE_CB, NULL);} else {nreactor_set_event(fd, read_callback, READ_CB, NULL);}return 0;}// 5k qpsint read_callback(int fd, int event, void *arg) {struct reactor *R = getInstance();unsigned char *buffer = R->head->items[fd].rbuffer;#if 0 //ETint idx = 0, ret = 0;while (idx < BUFFER_LENGTH) {ret = recv(fd, buffer+idx, BUFFER_LENGTH-idx, 0);if (ret == -1) { break;} else if (ret > 0) {idx += ret;} else {// == 0break;}}if (idx == BUFFER_LENGTH && ret != -1) {nreactor_set_event(fd, read_callback, READ_CB, NULL);} else if (ret == 0) {nreactor_set_event//close(fd);} else {nreactor_set_event(fd, write_callback, WRITE_CB, NULL);}#else //LTint ret = recv(fd, buffer, BUFFER_LENGTH, 0);if (ret == 0) { // finnreactor_del_event(fd, NULL, 0, NULL);close(fd);} else if (ret > 0) {unsigned char *sbuffer = R->head->items[fd].sbuffer;memcpy(sbuffer, buffer, ret);R->head->items[fd].slength = ret;printf("readcb: %s\n", sbuffer);nreactor_set_event(fd, write_callback, WRITE_CB, NULL);}#endif}// WEB server // ET / LTint accept_callback(int fd, int event, void *arg) {int connfd;struct sockaddr_in client;    socklen_t len = sizeof(client);    if ((connfd = accept(fd, (struct sockaddr *)&client, &len)) == -1) {        printf("accept socket error: %s(errno: %d)\n", strerror(errno), errno);        return 0;    }nreactor_set_event(connfd, read_callback, READ_CB, NULL);}

监听描述符变化

// accept --> EPOLLint reactor_loop(int listenfd) {struct reactor *R = getInstance();struct epoll_event events[POLL_SIZE] = {0};while (1) {int nready = epoll_wait(R->epfd, events, POLL_SIZE, -1);if (nready == -1) {continue;}int i = 0;for (i = 0;i < nready;i ++) {struct nitem *item = (struct nitem *)events[i].data.ptr;int connfd = item->fd;if (connfd == listenfd) { //item->acceptcb(listenfd, 0, NULL);} else {if (events[i].events & EPOLLIN) { //item->readcb(connfd, 0, NULL);} if (events[i].events & EPOLLOUT) {item->writecb(connfd, 0, NULL);}}}}return 0;}

完整代码实现

#define MAXLNE  4096#define POLL_SIZE1024#define BUFFER_LENGTH1024#define MAX_EPOLL_EVENT1024#define NOSET_CB0#define READ_CB1#define WRITE_CB2#define ACCEPT_CB3typedef int NCALLBACK(int fd, int event, void *arg);struct nitem { // fdint fd;//要监听的文件描述符int status;//是否在监听:1->在红黑树上(监听),0->不在(不监听)int events;//对应的监听事件,EPOLLIN和EPOLLOUT(不同的事件,走不同的回调函数)void *arg;//指向自己结构体指针#if 0NCALLBACK callback;#elseNCALLBACK *readcb;   // epollinNCALLBACK *writecb;  // epolloutNCALLBACK *acceptcb; // epollin#endifunsigned char sbuffer[BUFFER_LENGTH]; //int slength;unsigned char rbuffer[BUFFER_LENGTH];int rlength;};struct itemblock {struct itemblock *next;struct nitem *items;};struct reactor {int epfd;struct itemblock *head; };int init_reactor(struct reactor *r);int read_callback(int fd, int event, void *arg);int write_callback(int fd, int event, void *arg);int accept_callback(int fd, int event, void *arg);struct reactor *instance = NULL;struct reactor *getInstance(void) { //singletonif (instance == NULL) {instance = (struct reactor *)malloc(sizeof(struct reactor));if (instance == NULL) return NULL;memset(instance, 0, sizeof(struct reactor));if (0 > init_reactor(instance)) {free(instance);return NULL;}}return instance;}int nreactor_set_event(int fd, NCALLBACK cb, int event, void *arg) {struct reactor *r = getInstance();struct epoll_event ev = {0};//1if (event == READ_CB) {r->head->items[fd].fd = fd;r->head->items[fd].readcb = cb;r->head->items[fd].arg = arg;ev.events = EPOLLIN;}//2else if (event == WRITE_CB) {r->head->items[fd].fd = fd;r->head->items[fd].writecb = cb;r->head->items[fd].arg = arg;ev.events = EPOLLOUT;} //3else if (event == ACCEPT_CB) {r->head->items[fd].fd = fd;r->head->items[fd].acceptcb = cb;//回调函数r->head->items[fd].arg = arg;ev.events = EPOLLIN;}ev.data.ptr = &r->head->items[fd];if (r->head->items[fd].events == NOSET_CB) {if (epoll_ctl(r->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {printf("epoll_ctl EPOLL_CTL_ADD failed, %d\n", errno);return -1;}r->head->items[fd].events = event;} else if (r->head->items[fd].events != event) {if (epoll_ctl(r->epfd, EPOLL_CTL_MOD, fd, &ev) < 0) {printf("epoll_ctl EPOLL_CTL_MOD failed\n");return -1;}r->head->items[fd].events = event;}return 0;}int nreactor_del_event(int fd, NCALLBACK cb, int event, void *arg) {struct reactor *r = getInstance();struct epoll_event ev = {0};ev.data.ptr = arg;epoll_ctl(r->epfd, EPOLL_CTL_DEL, fd, &ev);r->head->items[fd].events = 0;return 0;}int write_callback(int fd, int event, void *arg) {struct reactor *R = getInstance();unsigned char *sbuffer = R->head->items[fd].sbuffer;int length = R->head->items[fd].slength;int ret = send(fd, sbuffer, length, 0);if (ret < length) {nreactor_set_event(fd, write_callback, WRITE_CB, NULL);} else {nreactor_set_event(fd, read_callback, READ_CB, NULL);}return 0;}// 5k qpsint read_callback(int fd, int event, void *arg) {struct reactor *R = getInstance();unsigned char *buffer = R->head->items[fd].rbuffer;#if 0 //ETint idx = 0, ret = 0;while (idx < BUFFER_LENGTH) {ret = recv(fd, buffer+idx, BUFFER_LENGTH-idx, 0);if (ret == -1) { break;} else if (ret > 0) {idx += ret;} else {// == 0break;}}if (idx == BUFFER_LENGTH && ret != -1) {nreactor_set_event(fd, read_callback, READ_CB, NULL);} else if (ret == 0) {nreactor_set_event//close(fd);} else {nreactor_set_event(fd, write_callback, WRITE_CB, NULL);}#else //LTint ret = recv(fd, buffer, BUFFER_LENGTH, 0);if (ret == 0) { // finnreactor_del_event(fd, NULL, 0, NULL);close(fd);} else if (ret > 0) {unsigned char *sbuffer = R->head->items[fd].sbuffer;memcpy(sbuffer, buffer, ret);R->head->items[fd].slength = ret;printf("readcb: %s\n", sbuffer);nreactor_set_event(fd, write_callback, WRITE_CB, NULL);}#endif}// web server // ET / LTint accept_callback(int fd, int event, void *arg) {int connfd;struct sockaddr_in client;    socklen_t len = sizeof(client);    if ((connfd = accept(fd, (struct sockaddr *)&client, &len)) == -1) {        printf("accept socket error: %s(errno: %d)\n", strerror(errno), errno);        return 0;    }nreactor_set_event(connfd, read_callback, READ_CB, NULL);}int init_server(int port) {int listenfd;    struct sockaddr_in servaddr;    char buff[MAXLNE];     if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {        printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);        return 0;    }     memset(&servaddr, 0, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    servaddr.sin_port = htons(port);     if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {        printf("bind socket error: %s(errno: %d)\n", strerror(errno), errno);        return 0;    }     if (listen(listenfd, 10) == -1) {        printf("listen socket error: %s(errno: %d)\n", strerror(errno), errno);        return 0;    }return listenfd;}int init_reactor(struct reactor *r) {if (r == NULL) return -1;int epfd = epoll_create(1); //int sizer->epfd = epfd;// fd --> itemr->head = (struct itemblock*)malloc(sizeof(struct itemblock));if (r->head == NULL) {close(epfd);return -2;} memset(r->head, 0, sizeof(struct itemblock));r->head->items = (struct nitem *)malloc(MAX_EPOLL_EVENT * sizeof(struct nitem));if (r->head->items == NULL) {free(r->head);close(epfd);return -2;}memset(r->head->items, 0, (MAX_EPOLL_EVENT * sizeof(struct nitem)));r->head->next = NULL;return 0;}// accept --> EPOLLint reactor_loop(int listenfd) {struct reactor *R = getInstance();struct epoll_event events[POLL_SIZE] = {0};while (1) {int nready = epoll_wait(R->epfd, events, POLL_SIZE, -1);if (nready == -1) {continue;}int i = 0;for (i = 0;i < nready;i ++) {struct nitem *item = (struct nitem *)events[i].data.ptr;int connfd = item->fd;if (connfd == listenfd) { //item->acceptcb(listenfd, 0, NULL);} else {if (events[i].events & EPOLLIN) { //item->readcb(connfd, 0, NULL);} if (events[i].events & EPOLLOUT) {item->writecb(connfd, 0, NULL);}}}}return 0;}int main(int arGC, char **argv) {     int  connfd, n;int listenfd = init_server(9999);nreactor_set_event(listenfd, accept_callback, ACCEPT_CB, NULL);//nreactor_set_event(listenfd, accept_callback, read_callback, write_callback);reactor_loop(listenfd);     return 0;}

到此,关于“C++中Reactor怎么实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: C++中Reactor怎么实现

本文链接: https://www.lsjlt.com/news/342479.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++中Reactor怎么实现
    这篇文章主要介绍“C++中Reactor怎么实现”,在日常操作中,相信很多人在C++中Reactor怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中Reactor怎么实现”的疑惑有所帮助!接下来...
    99+
    2023-07-02
  • C++中的Reactor原理与实现
    目录一、Reactor介绍二、代码实现一、Reactor介绍 reactor设计模式是event-driven architecture的一种实现方式,处理多个客户端并发的向服务端请...
    99+
    2024-04-02
  • Java中多线程Reactor模式怎么实现
    这篇文章主要讲解了“Java中多线程Reactor模式怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中多线程Reactor模式怎么实现”吧!多线程Reactor模式旨在分配多...
    99+
    2023-06-21
  • Reactor模型如何实现
    这篇文章主要介绍了Reactor模型如何实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Reactor模型如何实现文章都会有所收获,下面我们一起来看看吧。一. Reactor设计模式Reactor翻译过来的意...
    99+
    2023-07-05
  • Java中多线程Reactor模式的实现
    目录1、 主服务器2、IO请求handler+线程池3、客户端多线程Reactor模式旨在分配多个reactor每一个reactor独立拥有一个selector,在网络通信中大体设计...
    99+
    2024-04-02
  • 使用Reactor怎么实现一个Flink操作功能
    这篇文章给大家介绍使用Reactor怎么实现一个Flink操作功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。实现过程Flink对流式处理做的很好的封装,使用Flink的时候几乎不用关心线程池、积压、数据丢失等问题,...
    99+
    2023-06-06
  • C++基于reactor的服务器百万并发如何实现
    这篇文章主要介绍“C++基于reactor的服务器百万并发如何实现”,在日常操作中,相信很多人在C++基于reactor的服务器百万并发如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++基于reac...
    99+
    2023-07-02
  • C++基于reactor的服务器百万并发实现与讲解
    目录一、服务器的代码实现与讲解二、环境设置reactor实现的原理请参考:https://www.jb51.net/article/253794.htm本次百万并发的代码实现也是基于...
    99+
    2024-04-02
  • C++中怎么实现LeetCode
    今天就跟大家聊聊有关C++中怎么实现LeetCode,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。[LeetCode] 126. Word Ladder II 词语阶梯之二Given...
    99+
    2023-06-20
  • C++中怎么实现回文
    C++中怎么实现回文,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。下面是C++回文的判定算法:#include < iostream> ...
    99+
    2023-06-17
  • C++中的vector怎么实现
    今天小编给大家分享一下C++中的vector怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。vector介绍vecto...
    99+
    2023-07-05
  • C++中怎么实现多态
    C++中怎么实现多态,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。实现了C++多态 2 5 1 6#include < iostream>&nb...
    99+
    2023-06-17
  • C#中怎么实现多语言
    这篇文章给大家介绍C#中怎么实现多语言,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C#实现多语言的方法是通过配置文件实现,通过从配置文件中读取资源,然后在显示窗口的时候,即Load()方法中,动态显示相应的选择语言。...
    99+
    2023-06-17
  • 怎么在C++中实现AVL树
    怎么在C++中实现AVL树?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。AVL树的介绍AVL树是一种自平衡的二叉搜索树,它通过单旋转(single rotate)和双旋转(do...
    99+
    2023-06-15
  • c#中怎么实现sm4加密
    在C#中实现SM4加密可以通过使用第三方库来实现。一个常用的库是Bouncy Castle,可以通过NuGet安装。 首先,安装Bo...
    99+
    2024-04-02
  • C#中textbox换行怎么实现
    在C#中,可以通过在文本框中输入“\r\n”来实现换行。也可以使用Environment.NewLine属性来插入换行符。另外,如果...
    99+
    2023-06-14
    textbox换行
  • C#中怎么实现预处理
    这篇文章给大家介绍C#中怎么实现预处理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C#预处理C#预处理阶段是一个文本到文本的转换阶段,在预处理过程中,使能进行代码的条件包含和排除。pp-un it:&nbs...
    99+
    2023-06-18
  • C++怎么实现中国象棋
    这篇文章主要介绍“C++怎么实现中国象棋”,在日常操作中,相信很多人在C++怎么实现中国象棋问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++怎么实现中国象棋”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-25
  • C#中的继承怎么实现
    在C#中,继承是通过使用关键字" : "来实现的。下面是一个简单的示例,演示了如何在C#中实现继承: // 定义...
    99+
    2024-03-06
    C#
  • c++中string转int怎么实现
    在C++中,可以使用std::stoi函数将字符串转换为整数。示例如下: #include <iostream> #in...
    99+
    2024-03-15
    c++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作