当前位置: 首页 > news >正文

快速入门Socket编程——封装一套便捷的Socket编程——Reactor

快速入门Socket编程——封装一套便捷的Socket编程——Reactor 设计模式

​ 我们下面来聊一聊基于Epoll的Reactor 设计模式,这里构成了笔者设计的核心思路。

​ 我们可以直到Reactor 模式是一种典型的 事件驱动(Event-Driven)设计模式。我们一次性的监听多个 I/O 句柄的事件(可读、可写、异常)。这实际上是一种I/O 多路复用机制

I/O 多路复用机制(如 selectpollepoll):一个进程或线程可以同时监视多个文件描述符(File Descriptor, FD),并在其中任何一个文件描述符就绪(ready for I/O)时,得到通知并进行相应的操作,而无需阻塞在单个 I/O 操作上。

​ 当我们监听到了事件的来源的时候,我们就会Reactor 分发(dispatch)事件到对应的 Handler(事件处理器)

一句话理解:

Reactor 模式中,应用程序主动从内核查询事件,然后调用回调函数处理


Reactor 模式的角色

  1. Reactor(事件分发器)
    • 负责监听事件并分发给对应的 Handler。
  2. Handle(句柄)
    • I/O 资源,如 socket_fd
  3. Event Handler(事件处理器)
    • 负责响应某个 I/O 事件的回调函数

Reactor 的典型工作流程

​ 在笔者之后全面的介绍代码的时候,会详细的说明,这里给出一个片段:

void LinuxServerSocket::start_workloop(const ServerWorkers& worker) {internal_worker = worker;std::vector<epoll_event> events(max_epoll_contains);while (!shell_terminate) {int nfds = epoll_wait(epfd, events.data(), max_epoll_contains, -1);for (int i = 0; i < nfds; ++i) {int current_fd = events[i].data.fd;if (current_fd == socket_fd) {handle_new_connections(); // 新连接 -> accept_callback} else {react_clients(current_fd); // 数据 -> receiving_callback}}}
}

​ 这里就是一个经典的Reactor设计模式代码的流程:

  1. 注册事件:Reactor 注册 socket 和其关注的事件(如 EPOLLIN)。
  2. 等待事件:调用 epoll_wait()(或 select/poll)。
  3. 事件分发:将就绪事件分发给对应的事件处理器。
  4. 执行回调:事件处理器完成业务逻辑。

​ 在上面这里的 epoll_wait()Synchronous Event Demultiplexer(同步事件分发器),accept_callbackreceiving_callback 是事件处理器。


1.4 Reactor 的特点

  • 被动反应:Reactor 是“被动”的,只能处理已就绪的事件。
  • 同步 I/O:内核只负责通知“可读/可写”,真正的 read()/write() 由应用程序完成。
  • 适合高并发 I/O:结合 epoll,可以处理成千上万的连接。

补充:Proactor 设计模式

Proactor 的定义

  • Proactor 模式是一种异步非阻塞 I/O 模型。它的核心思想是:当 I/O 操作完成后,才通知应用程序,并把操作结果(包括读取的数据或写入的字节数)一并传递给应用程序。

    可以把 Proactor 模式想象成一个“送餐上门系统”:

    1. 你(应用程序) 去餐厅点餐并付款。
    2. 老板(操作系统) 告诉你:“饭好了会给你送过来。”
    3. 你在座位上(应用程序继续做其他事情) 不用管。
    4. 饭好了,服务员把餐端到你面前(I/O 操作完成,操作系统通知应用程序并传递结果)

一句话理解:

Proactor 模式中,应用程序只提交操作请求,内核在后台完成 I/O 后直接调用回调通知


核心组件:
  • 异步操作发起者 (Asynchronous Operation Initiator):应用程序发起异步 I/O 操作(例如,aio_read,在 Windows 上是 ReadFileEx)。
  • 异步事件多路分发器 (Asynchronous Event Demultiplexer):操作系统内核负责管理和完成异步 I/O 操作。
  • 完成处理器 (Completion Handler):操作系统在 I/O 操作完成后,会调用应用程序注册的这个回调函数,并将操作结果(如读取到的数据)作为参数传递给它。
工作流程:
  1. 应用程序发起一个异步 I/O 操作(例如,read 到某个缓冲区)。
  2. 操作系统内核接管这个 I/O 操作,立即返回,应用程序可以继续执行其他任务。
  3. 当 I/O 操作在内核中完全完成后(数据已经读取到缓冲区,或者数据已经发送完毕),内核会通知应用程序。
  4. 操作系统调用应用程序注册的完成处理器,将 I/O 操作的结果传递给它。

Proactor 的工作流程

  1. 应用程序发起异步操作(如 aio_read() 或 Windows IOCP 的 ReadFileEx())。
  2. 内核异步完成 I/O。
  3. 内核通知应用程序(通过回调、完成端口等机制)。
  4. 应用程序直接处理已完成的数据,无需再调用 read()

Reactor vs Proactor 对比

特点ReactorProactor
I/O 类型同步非阻塞 I/O异步 I/O
谁执行 I/O应用程序主动 read/write内核完成 I/O
触发时机通知“就绪”通知“完成”
常用平台epoll (Linux)、select/pollIOCP (Windows)、POSIX AIO

类比:

  • Reactor:门铃响了,你要去开门拿快递。
  • Proactor:快递小哥直接把快递送进家里,你只需处理包裹。

为什么项目选择 Reactor
  • Linux 原生提供的 epoll就绪通知 模型,不会替咱们完成 recv()
  • Proactor 在 Linux 中实现比较复杂,需要 io_uring 或 POSIX AIO,而 epoll + Reactor 模式成熟且高效。
http://www.dtcms.com/a/297255.html

相关文章:

  • 【AMD平台】编译llama.cpp
  • 【问题集】——RAG项目实战:LangChain 0.3集成 Milvus 2.5向量数据库,构建大模型智能应用
  • GTSuite许可与网络安全
  • 每天算法刷题Day53:7.25:leetcode 栈5道题,用时1h35min
  • 广东省省考备考(第五十六天7.25)——常识:科技常识(听课后强化训练)
  • 输电线路观冰精灵在线监测装置:科技赋能电网安全的新利器
  • 微算法科技(NASDAQ:MLGO)采用分布式哈希表优化区块链索引结构,提高区块链检索效率
  • 在FreeBSD系统下使用llama-cpp运行飞桨开源大模型Ernie4.5 0.3B(失败)
  • C++ atomic与内存顺序 【转】
  • 从双碳到零碳园区:安科瑞微电网系统的应用与价值
  • Javaweb————学习javaweb的预备知识
  • 【数据结构】长幼有序:树、二叉树、堆与TOP-K问题的层次解析(含源码)
  • 【js】Proxy学习笔记
  • 【高等数学】第五章 定积分——第四节 反常积分
  • Colab中如何临时使用udocker(以MinIO为例)
  • 华为云DRS实现Oracle到GaussDB数据库迁移的全流程技术方案
  • Android Studio 自带的官方模拟器,ABI这一列是x86_64,xABI这一列是arm64-v8a
  • 【面试场景题】外卖点餐系统设计思路
  • mysql 和oracle的选择
  • Android Studio 2024 内嵌 Unity 3D 开发示例
  • Oracle转Mysql建表脚本
  • Android studio自带的Android模拟器都是x86架构的吗,需要把arm架构的app翻译成x86指令?
  • 【Android Studio】安装Trae插件后Android Studio 启动崩溃问题处理
  • 瑞萨电子RA-T MCU系列新成员RA2T1——电机控制专家
  • CPU(中央处理器)和GPU(图形处理器)的区别
  • vscode npm run build打包报ELIFECYCLE
  • 一文解析公平锁、非公平锁、悲观锁、乐观锁、可重入锁和锁的升级(含详细代码实例)
  • MJ11032G和MJ11033G是对管由onsemi/安森美公司研发的一款高性能、低功耗的达林顿晶体管
  • 能源管理网页的碳中和视觉语言:数据图表中的环保色彩体系创新
  • 基于51单片机的光照强度检测系统Protues仿真设计