50.Reactor反应堆模式

使用ET+非阻塞,设计出一个正确IO的服务器

读取的时候要保证读取的数据来自对应的fd,发过来的报文即使读完了(ET模式必须读完)也大概率不是完整的(TCP面向字节流),但这个报文又不能丢,必须存着 -> 因此给每个fd,定义收发缓冲区 -> 把每个fd封装一下 --- Connection

listensocket和普通socket,有区别吗?本质上没有区别,只不过listensocket等待的是连接就绪,也是读就绪 -> listensocket使用继承的方式来实现统一

具体流程简图:

易错点1:

在send时,有两种情况:

1)_outbuffer写完了

2)_outbuffer没发完,内核发送缓冲区被占满了

**第二种情况:需要开启对于写事件的关心。**下次wait成功,再写如果还是满就继续开启写事件关心;再写如果写完了,就把对应的写事件关心去掉。

注意:EnableWREvent时,EPOLLET别写漏了;除了内核修改,Reactor内部的_connections也要修改。

易错点2:

实现回调机制时,每个Connection都要有一份。首先上层的listener注册回调,listener进行recv(accept)时,给每个新的Connection(Channel)都拷贝一份,这样每个Channel都有一份回调。

细节点1:

每个Connection内部都有一个Reactor类型的回指指针,便于操作_connections 和 _epoll_ptr进行用户和内核的数据修改。

多路转接的发送问题

接收缓冲区默认不就绪,发送缓冲区默认就绪(写事件默认就绪)。
结论:

1)读时间关心需要常设,而写事件关心是按需设置!如果写事件常设了,epoll就会一直写事件就绪

**2)写事件应该如何按需设置?如何发送?**直接发送,把发送缓冲区写满了(写事件不就绪),再把对写事件关心设置到内核。

3)手动开启对EPOLLOUT的关心,默认就要触发一次写事件就绪(ET也会触发)

Reactor多进程多线程实现方案分析

如果是用一个Reactor给多线程或者多进程用,那么它们可能epoll_wait就绪时拿到同一个文件描述符,多执行流同时向文件里写或读,会有线程安全问题。

最佳实践:一个执行流一个Reactor(One thread one Loop)

多进程实现方案

注:accept线程安全

1)主进程创建Reactor,创建listensock并添加后,创建一批子进程,有对应的管道连接(进程池)

2)主进程用epoll_wait时,有连接到来了,listensock读事件就绪了,但只是向对应的管道内发送revents,唤醒特定进程(负载均衡)。

3)特定进程被唤醒,读到revents,转而去listensock(从主进程继承下来的)去获取新连接添加到Reactor中,根据revents处理对应就绪的事件进行处理

多线程实现方案

1)主线程有一个Reactor,内部有listensock;创建一批线程,通过eventfd进行唤醒(负载均衡),各自有各自的Reactor

2)主线程epoll_wait只关心listensock的读事件,将获取到的sockfd入到一个队列中(加锁),唤醒一个特定线程(负载均衡)

3)被唤醒线程从加锁队列中读sockfd,然后添加到自己的Reactor,从此往后只关心自己Reactor的sockfd(子线程独自的Reactor内部没有listensock)

eventfd

  • eventfd 是一个轻量级的事件通知机制,基于文件描述符。
  • 它可以与 I/O 多路复用机制(如 epoll )结合使用。
  • 内核维护一个 64 位的计数器, write 会增加计数器, read 会减少计数器。

Reactor单进程版代码:

Linux-remote: linux远程仓库https://gitee.com/its-quite-six/linux-remote/tree/master/25_10_2/Reactor

相关推荐
筱羽_筱羽5 小时前
跟着“Ubuntu18.04/20.04编译Linux5.10.76+Xenomai-3.2.1+IgH”教程遇到的问题
linux·运维·ubuntu
ShineWinsu6 小时前
对于Linux:基于UDP实现简单聊天室功能
linux·c++·面试·udp·笔试·进程·简单聊天室
zoipuus6 小时前
上传repo仓库到自己的gitlab
linux·gitlab·shell·全志·tina
IT大白鼠6 小时前
CVE-2026-7531 Azure Linux MariaDB PQC 内存破坏漏洞详解
linux·mariadb·azure·cve-2026-7531
无忧.芙桃6 小时前
线程同步与线程互斥(上)
linux·运维·操作系统·运维开发
HAPPY酷7 小时前
【ROS2】16G 内存笔记本跑 ROS2 仿真?VMware 虚拟机“保姆级”配置指南 (R9 7940HX + RTX 4060)
java·linux·ide·windows·pycharm
donoot16 小时前
Linux系统下图书馆级电子书全自动标准化分类整理完整实施方案
大数据·linux·运维·电子书管理
Felix-lxd17 小时前
Ubuntu 22.04 配置 Nginx
linux·nginx·ubuntu
Tim_Van18 小时前
在 CentOS 7 中安装 Chromium 的完整步骤
linux·运维·chrome·centos
2023自学中18 小时前
C++ 内存追踪器
linux·c++