从0实现Reactor高并发服务器
文章平均质量分 93
记录实现Reactor高并发服务器的开发过程
榆榆欸
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
19.增强异步日志系统:实现日志滚动、优化时间戳与线程 ID 处理
为了防止日志文件过大,我们在日志文件大小到达预定的大小后,就要新创建一个日志文件来使用,或者通过时间(每天零点)去新建一个文件。一个典型的日志文件的文件名如下:logfile_test.20221122_140210.hostname.3605.log一共5部分:1.logfile_test是服务器的进程名字;2.时间;3.主机名;4.进程id;5.后缀 .log。看看LogFile中需要新添加的成员 其构造函数的参数有了变化,把文件名字改成了基础文件名字,添加了滚动日志的大小和需要冲刷的时间原创 2025-04-02 18:47:51 · 829 阅读 · 0 评论 -
18.实现异步日志:日志输出到磁盘文件
在上一节中我们实现了同步日志,并输出到stdout。这节我们来实现异步。在上一节中,添加了Append,这是对文件操作的一个底层的类,我们需要一个更加上层的,使用更便捷的接口来操控磁盘文件。比如说每输出了1000条日志消息,就需要冲刷AppendFile类中的缓冲区buffer_;还有日志文件大小若达到了预定的大小,就要新开一个日志文件等等。所以我们新创一个类,更加方便我们使用。原创 2025-04-02 16:12:08 · 745 阅读 · 0 评论 -
17.添加异步日志:日志消息的存储与输出机制
怎么要创建这么多类呀,感觉又是不爽。那这里就要想清楚,这些类的作用是干什么的呢,一定要一一对应起来。我们新建了这么多类是为了可以。原创 2025-04-02 15:10:11 · 954 阅读 · 0 评论 -
16. 完善定时器功能:通过 EventLoop 实现定时器的增删操作
上一节已经完善了定时器容器类TimerQueue,该类内部有三个容器,一定要区分清楚这三个容器的作用。这一节就来讲讲用户是如何去增添或删除定时器的。首先要明确TimerQueue是内部类,用户是看不见的,不能直接去调用的。而由之前写的main函数中可知外部可给用户使用的主要是。而我们的TimerQueue类中有个成员变量类对象loop_,这个表明是在哪个loop线程去执行定时器。所以我们可以通过EventLoop类去调用TimerQueue类。。那EventLoop类中也主要就关于这两个接口的调用。原创 2025-04-02 11:45:12 · 598 阅读 · 0 评论 -
15.实现高效定时器:Timestamp、Timer 类与 TimerQueue 容器的设计与分析
我们这一节添加了Timestamp类,该类是对时间戳的封装,也是为了方便定时器使用有关时间的函数。添加了Timer类,Timer类就是对应一个超时任务,保存了超时时刻Timestamp,超时回调函数,以及超时任务类型(一次 or 周期)。接着讲解了如何在linux中实现定时,选择的定时函数,timerfd_* 系列函数的使用。最后到了管理多个定时的类TimerQueue。讲解了选择哪种数据结构来进行管理定时器。该类需要解决比较多问题,其类内部有三个容器,一定要清楚哪个容器是解决了哪个问题的。原创 2025-04-02 11:32:22 · 910 阅读 · 0 评论 -
14.主从Reactor+线程池模式,Connection对象引用计数的深入分析
这Connection的引用计数变化和前面提到的两个函数中的lambda表达式为什么使用值传递也就很好理解了。这一节的代码改动是很小的,很小的变化就可以组合成主从Reactor+thread pool模式,也很好理解。所以可以说这节最重要的是理解其Connection的引用计数的变化,通过画出的这个图和讲解,应该可以深入地理解其引用计数的变化了。原创 2025-04-02 10:35:55 · 927 阅读 · 0 评论 -
13.主从 Reactor 模式的实现
因为loop_可能在其他地方访问,而IO线程函数退出时,线程已经不能继续运行,代表IO线程EventLoop的loop_也就没有了存在意义。如果不清空,析构函数可能会导致重复调用loop_->quit(),让IO线程loop循环重复退出。原创 2025-04-01 18:34:59 · 946 阅读 · 0 评论 -
12.实现跨线程安全调用函数
上一节我们添加了线程池,可以把一些比较耗时的任务放到线程池中处理。而我们处理完成后,需要把数据发送给回客户端,而上一节中,是在线程池的某一线程中把消息发送的,不是在IO线程发送。这样是有点问题,首先,这样就会有两个线程去控制该socket(IO线程会监听该socket的读写,而线程池又通过send()函数去调用该socket),这不符合我们的要求的。。那么,我们该怎么解决这个问题呢。原创 2025-04-01 16:04:57 · 693 阅读 · 0 评论 -
11.实现单Reactor与线程池的结合
回想一下单单线程模式,其伪代码简单来说,其是一个while循环,通过handleEvent()回调函数来执行与用户的请求操作,若handleEvent()函数要处理的事情是比较耗时的操作,比如一些长时间的计算等等,那这样就会堵塞在channel[i]->handleEvent();这句代码中,就可能不能及时有响应。原创 2025-03-31 21:20:15 · 831 阅读 · 0 评论 -
10.完善 Connection 类,单 Reactor 单线程模式成型
Reactor就是核心类EventLoop,就是一个循环。简单点说,其实就是一个epoll,通过epoll_wait()函数来进行dispatch。黄色的read(),send()这些就是可以看成是Connection类。这样,基础的单Reactor的模型就形成了。这是一个重要的版本,之后的版本都是在这个基础上面添加内容的,例如需要使用多线程。原创 2025-03-31 20:03:15 · 908 阅读 · 0 评论 -
9.解析Muduo的Connection类
这里还是。原创 2025-03-31 19:31:36 · 1039 阅读 · 0 评论 -
8.非阻塞网络编程中的Buffer类
这节需要我们明白为什么non_blocking网络编程中应用层的buffer是必要的。这节的很多内容都是陈硕《Linux多线程服务器编程》书中的内容原话。在使用epoll时,我们通常会结合非阻塞 I/O。非阻塞 I/O 的核心理念是防止在read()write()或其他 I/O 系统调用上出现阻塞,从而使得控制线程得到最大的复用。I/O 线程仅会在 I/O 多路复用函数(如selectpollepoll_wait)上进行阻塞。因此,应用层缓冲区显得非常重要,每个 TCP 套接字都需要具备有状态的和。原创 2025-03-31 14:24:05 · 604 阅读 · 0 评论 -
7.从Server到Acceptor,优化Reactor模式的实现
在上一节中,我们实现了的核心结构,创建了一个Server类,并且注意到许多逻辑集中在这个类中。一个简单的服务器程序主要由两部分组成:一部分是accept(2),另一部分是(即 TCP 连接)。为了提高代码的清晰度和可维护性,我们可以将Server类的这些功能进行分离。首先,我们可以创建一个新的类,称为,专门处理建立连接的逻辑。原创 2025-03-31 11:27:00 · 949 阅读 · 0 评论 -
6.实现 Reactor 模式的 EventLoop 和 Server 类
在上一节中,我们添加了Channel类,这已经进入到开始实现。这时我们为添加到epoll上的文件描述符都添加了一个Channel。每个Channel都可以拥有自己的回调函数,即用户可以按照自己的想法去往epoll中注册事件,之后可以根据不同的事件类型调用指定的回调函数。但上一章节还没有实现增添回调函数和调用回调函数,这一节来完成其实现。原创 2025-03-31 10:52:43 · 1079 阅读 · 0 评论 -
5.实现 Channel 类,Reactor 模式初步形成
通过这一节的修改,我们可以获得关于epoll返回的活跃的文件描述符的更多信息,添加了Channel类。按照上面的思路,我们可以把firstTime和fd构成一个结构体,之后就使用联合体epoll_data的ptr,不使用fd。那么我们可以把一个文件描述符封装成一个类,这个类里面有更多的关于这个文件描述符的信息,我们把他叫做Channel类,那就可以指向任何一块地址空间,也可以指向一个类对象,这就可以包含关于这个文件描述符的更多信息。data,这是一个联合体。,这不符合我们的要求的,这将在下一节中进行修改。原创 2025-03-30 15:40:07 · 829 阅读 · 0 评论 -
4.Socket类、InetAddr类、Epoll类实现模块化
pragma once // 确保该头文件只被包含一次#include <string> // 引入字符串类#include <arpa/inet.h> // 提供网络地址结构定义及函数#include <stdio.h> // 标准输入输出库public:// 默认构造函数InetAddr();// 带参数的构造函数,接受端口和可选的IP地址// 获取sockaddr_in结构的指针,供外部使用// 设置sockaddr_in结构的地址,供外部使用// 将地址转换为IP字符串格式。原创 2025-03-28 22:11:55 · 664 阅读 · 0 评论 -
3.使用epoll实现单线程并发服务器
多路复用:指可以同时监控多个网络连接,并在同一线程中处理这些连接。epoll在处理大量并发连接时,性能通常优于select和poll,特别是在连接数达到上万的情况下。epoll是Linux特有的特性,无法在其他操作系统上使用。原创 2025-03-26 15:04:42 · 1169 阅读 · 0 评论 -
2.基于多线程的TCP服务器实现
在我们预想中,服务器端应该能够同时与多个客户端建立连接并进行网络通信。然而,在之前的代码中,服务器实现只支持单一连接,因为在处理连接时,主线程会被accept()read()或write()等方法阻塞,导致无法响应新的连接请求。为了解决这一问题,本文将介绍如何实现一个多线程的TCP服务器,让我们来一步步分析并构建代码。原创 2025-03-26 00:03:10 · 752 阅读 · 0 评论 -
1.基于TCP的简单套接字服务器实现
在本文中,我们将深入了解套接字(socket)及其在网络通信中的应用,特别是如何在服务器端创建一个基于TCP的简单通信框架。套接字是程序员进行网络通信的一组接口,主要分为客户端和服务器端。在这篇文章中,我们将重点关注服务器端的实现。原创 2025-03-25 23:00:24 · 821 阅读 · 0 评论
分享