TinyWebServer源码解析——Reactor和Proactor双模式web组件

TinyWebServer源码解析——Reactor和Proactor双模式web组件

项目地址
https://github.com/qinguoyi/TinyWebServer.git
尊重开源精神,保障作者权益,内容均为原创,如有雷同,纯属巧合

本文件是将TinyWebSever其他组件串联起来的文件,笔者水平有限,仅能挖出这些技术栈,以供讨论,仅个人观点,如有错误,还望海涵!

定义了一个WebServer类

通过整个服务器程序的主控逻辑与核心调度模块,实现了一个高性能、可配置、支持 Reactor/Proactor 双模式的微型 Web 服务器


封装内容:
  1. 构造函数初始化所有成员为安全初值
  2. 析构函数释放所有动态资源
  3. void init()函数接收用户配置参数
  4. void trig_mode()函数设置epoll触发模式
  5. void log_write()函数初始化日志系统
  6. void sql_pool()函数创建MYSQL连接池
  7. void thread_pool()函数创建线程池,后续HTTP请求对象提交给线程池异步处理
  8. void eventListen()函数完成网络监听准备
  9. void eventLoop()函数主事件循环
  10. bool dealclientdata()函数处理新客户端连接
  11. bool dealwithsignal()函数从信号管道读取信号
  12. void dealwithread()函数处理可读事件
  13. void dealwithwrite()函数处理可写事件
  14. void timer()函数为新连接创建定时器

核心函数:
voidinit(int port , string user, string passWord, string databaseName,int log_write ,int opt_linger,int trigmode,int sql_num,int thread_num,int close_log,int actor_model);
  1. init()函数初始化端口,数据库,日志,触发模式,线程数,其否启用Reactor模式
    • void trig_mode()设置listenfd和connfd的epoll触发模式
    • log_write()初始化日志系统(单例 Log)
    • sql_pool():创建 MySQL 连接池,并初始化用户表缓存
    • thread_pool()创建 threadpool<http_conn>,用于异步处理请求
    • eventListen()创建监听 socket、epoll、信号管道、设置信号处理
  2. void eventLoop()网络事件循环,基于epoll_wait实现高性能I/O多路复用
事件类型处理函数说明
新连接 (m_listenfd)dealclientdata()接受新客户端,初始化 http_conn 和定时器
信号通知 (m_pipefd[0])dealwithsignal()处理 SIGALRM(定时)和 SIGTERM(退出)
可读事件 (EPOLLIN)dealwithread()读取 HTTP 请求
可写事件 (EPOLLOUT)dealwithwrite()发送 HTTP 响应
  1. m_actormodel模式处理
    • m_actormode == 0 时(Proactor模式)
      • 主线程完成完整I/O操作
      • 将已读取/待发送的http_conn对象放入线程池,仅执行process()
    • m_actormode == 1 时(Reactor模式)
      • 主线程只负责事件通知
      • 线程池的工作线程执行实际I/O+process
  2. 定时器管理:
    • 使用基于链表的定时器
    • 每个新连接创建一个定时器
    • 每次读写成功则adjust_timer()延长超时时间
    • 超时或出错就调用deal_timer()
类别函数功能
生命周期构造 / 析构资源初始化与释放
初始化init, trig_mode, log_write, sql_pool, thread_pool, eventListen配置与启动准备
主循环eventLoop驱动整个服务器运行
事件处理dealclientdata, dealwithsignal, dealwithread, dealwithwrite响应 epoll 事件
定时器timer为连接设置超时
工具addfd, modfd, show_error辅助 I/O 与错误处理

触发模式:
  1. LT(水平触发):epoll默认模式
    • 只要fd处于就绪状态就会持续通知
  2. ET(边缘触发):
    • 只当fd状态改变时,触发一次
    • 需配合非阻塞I/O+循环读写
    • 循环读写一般使用while循环,不用for循环是为了避免虚假唤醒
  3. 参数组合
// trigmode 参数决定组合: 0: LISTEN_LT + CONN_LT (最安全) 1: LISTEN_LT + CONN_ET (常用) 2: LISTEN_ET + CONN_LT 3: LISTEN_ET + CONN_ET (最高性能,但 listenfd 也需循环 accept) 

Reactor模式
    • 创建socket
    • 绑定地址与端口
    • 开始监听
    • epoll
  1. 事件处理
    • 当事件循环发现fd就绪后,执行相应的义务逻辑
    • 常见类型

事件循环

while(!stop_server){int n =epoll_wait(epollfd, events, MAX_EVENTS,-1);for(int i =0; i < n; i++){int fd = events[i].data.fd;if(fd == listenfd){// 处理新连接 }elseif(events[i].events & EPOLLIN){// 处理可读事件 }elseif(events[i].events & EPOLLOUT){// 处理可写事件 }}}

网络监听

int listenfd =socket(AF_INET, SOCK_STREAM,0);
bind(listenfd,(structsockaddr*)&addr,sizeof(addr));
listen(listenfd,5);// 5 是 backlog,等待队列长度
事件类型触发条件处理动作
新连接listenfd 可读调用 accept() 获取 connfd,初始化连接对象
可读事件(EPOLLIN)客户端发送了数据调用 read() 读取 HTTP 请求
可写事件(EPOLLOUT)socket 发送缓冲区有空位调用 write() 发送 HTTP 响应
错误/关闭对端关闭连接或出错清理资源,关闭 fd
    • 信号是异步的
    • 创建一个 socketpair 或 pipe(两个 fd,一端写,一端读)。
    • 注册读端到 epoll
    • 在信号处理函数中,只向写端写一个字节(如 '1')。
    • 主循环的 epoll_wait 会检测到读端可读,从而在主线程安全上下文中处理信号。
    • 将异步信号转换为同步I/O
  1. 可读事件和可写事件
    • 可读事件:
      • fd的接收缓冲区有数据可读
      • 调用read()或recv()读取数据
    • 可写事件:
      • fd的发送缓冲区由空闲空间,可以写入数据
      • 调用write()或send()发送数据

信号管道

// 初始化 socketpair(PF_UNIX, SOCK_STREAM,0, m_pipefd);// 信号处理函数voidaddsig(int sig,void(handler)(int)){structsigaction sa; sa.sa_handler = handler;sigaction(sig,&sa,NULL);}// SIGALRM 处理函数 voidalarm_handler(int sig){send(m_pipefd[1],"1",1,0);// 只写1字节! }// 主循环中 if(sockfd == m_pipefd[0]){dealwithsignal();// 安全地读取并处理信号 }

新连接

信号

connfd 可读

connfd 可写

yes

yes

启动服务器

创建 listenfd 并监听

创建 epoll + 信号管道

注册 listenfd 和 pipefd 到 epoll

进入 eventLoop

epoll_wait 返回事件?

dealclientdata: accept + 初始化 connfd

dealwithsignal: 读管道,设置 timeout/stop

dealwithread: 读 HTTP 请求

dealwithwrite: 发 HTTP 响应

将 connfd 加入 epoll 监听

提交任务到线程池处理请求

发送响应,若未发完则重注册 EPOLLOUT

生成响应内容

是否timeout

关闭超时连接

是否stop_server

退出循环,清理资源

Read more

近五年体内微/纳米机器人赋能肿瘤精准治疗综述:以 GBM 为重点

近五年体内微/纳米机器人赋能肿瘤精准治疗综述:以 GBM 为重点

摘要 实体瘤治疗长期受制于递送效率低、肿瘤组织渗透不足以及免疫抑制与耐药等问题。传统纳米药物多依赖被动累积与扩散,难以在肿瘤内部形成均匀有效的药物浓度分布。2021–2025 年,体内微/纳米机器人(包括外场驱动微型机器人、自驱动纳米马达以及生物混合机器人)围绕“运动能力”形成了三条相互收敛的技术路线: 其一,通过磁驱、声驱、光/化学自驱等方式实现运动增强递药与深层渗透,将治疗从“被动到达”推进到“主动进入”; 其二,与免疫治疗深度融合,实现原位免疫唤醒与肿瘤微环境重塑; 其三,针对胶质母细胞瘤(glioblastoma, GBM)等难治肿瘤,研究趋势转向“跨屏障递送(BBB/BBTB)+ 成像/外场闭环操控 + 时空可控释放”的系统工程。 本文围绕“运动—分布—疗效”的因果链条,总结 2021–2025 年代表性研究与关键评价指标,讨论临床转化所需的安全性、

By Ne0inhk

Moonshine专为端侧/边缘设备做的深度架构优化+可变长度推理+隐私原生+多语言强适配

一、架构与推理效率:端侧原生设计(核心优势) 1. 可变长度输入,无强制30秒窗口 * Whisper固定30秒块,短音频也要填充到30秒再处理,固定开销大。 * Moonshine支持任意长度音频,计算量与音频长度线性正比,短音频(1–3秒)速度提升5–15倍。 * 延迟:10秒音频在手机/树莓派上仅50–150ms,Whisper同条件约500–1500ms。 2. 轻量化Transformer+高效算子 * 基于Transformer但大幅精简,参数仅27M–245M(Tiny/Base/Medium),远小于Whisper同定位模型。 * 采用旋转位置嵌入(RoPE),更好捕捉语音时序,减少冗余计算。 * 推理引擎深度优化,支持INT8/FP16量化,内存占用再降70%+。 3. 流式/实时推理原生支持 * 内置流式解码,边录边转,无需等整段音频结束。 * 端到端延迟**<50ms*

By Ne0inhk
开发兜不住?让数据库来兜底:金仓 SQL 防火墙的工程化实践

开发兜不住?让数据库来兜底:金仓 SQL 防火墙的工程化实践

开发兜不住?让数据库来兜底:金仓 SQL 防火墙的工程化实践 在真实的生产环境中,数据库安全从来不是“写完代码就结束”的问题,而是一个贯穿系统生命周期的持续对抗过程。哪怕你已经严格执行参数化查询、ORM 框架封装、输入校验等规范,仍然无法保证系统绝对无注入风险——遗留系统、动态 SQL、第三方组件、甚至临时脚本,都会成为潜在突破口。 这也是为什么越来越多企业开始将防线下沉到数据库层:既然应用层不可控,那就让数据库成为最后一道“强制执行的安全边界”。 本文结合 KingbaseES 的 SQL 防火墙机制,从原理、模式设计到性能表现,讲清楚它是如何在工程上解决 SQL 注入问题的。 一、SQL 注入的本质:语义劫持,而不是“字符串拼接问题” 很多人对 SQL 注入的理解还停留在“拼接字符串不安全”,但从数据库视角来看,本质其实是: 攻击者篡改了 SQL 的语义结构(

By Ne0inhk
【Linux】——从0到1的学习,让你熟练掌握,带你玩转Linux,教你安装Java常用软件、及spring boot项目部署

【Linux】——从0到1的学习,让你熟练掌握,带你玩转Linux,教你安装Java常用软件、及spring boot项目部署

🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大三学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL,Java基础,Rust】 🎈热门专栏:🎊【Python,Javaweb,Springboot】  感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️ 目录 🎈Linux安装 🎁安装步骤 🎁网卡设置 🎁目录功能及介绍  🎈常用命令 🎁初体验 🎟命令  🎟实战 🎟出现乱码 🎟小技巧 🎟Linux命令格式 🎁文件目录操作命令 🎟ls 🎟cd 🎟cat 🎟more 🎟tail 🎟rmdir 🎟rm 🎁拷贝移动命令 🎟cp 🎟mv 🎁打包压缩命令 🎟tar 🎁文本编辑 🎟vi/vim 🎗命令模式 🎗插入模式

By Ne0inhk