自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(127)
  • 收藏
  • 关注

原创 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 666

原创 18.实现异步日志:日志输出到磁盘文件

在上一节中我们实现了同步日志,并输出到stdout。这节我们来实现异步。在上一节中,添加了Append,这是对文件操作的一个底层的类,我们需要一个更加上层的,使用更便捷的接口来操控磁盘文件。比如说每输出了1000条日志消息,就需要冲刷AppendFile类中的缓冲区buffer_;还有日志文件大小若达到了预定的大小,就要新开一个日志文件等等。所以我们新创一个类,更加方便我们使用。

2025-04-02 16:12:08 611

原创 17.添加异步日志:日志消息的存储与输出机制

怎么要创建这么多类呀,感觉又是不爽。那这里就要想清楚,这些类的作用是干什么的呢,一定要一一对应起来。我们新建了这么多类是为了可以。

2025-04-02 15:10:11 799

原创 16. 完善定时器功能:通过 EventLoop 实现定时器的增删操作

上一节已经完善了定时器容器类TimerQueue,该类内部有三个容器,一定要区分清楚这三个容器的作用。这一节就来讲讲用户是如何去增添或删除定时器的。首先要明确TimerQueue是内部类,用户是看不见的,不能直接去调用的。而由之前写的main函数中可知外部可给用户使用的主要是。而我们的TimerQueue类中有个成员变量类对象loop_,这个表明是在哪个loop线程去执行定时器。所以我们可以通过EventLoop类去调用TimerQueue类。。那EventLoop类中也主要就关于这两个接口的调用。

2025-04-02 11:45:12 536

原创 15.实现高效定时器:Timestamp、Timer 类与 TimerQueue 容器的设计与分析

我们这一节添加了Timestamp类,该类是对时间戳的封装,也是为了方便定时器使用有关时间的函数。添加了Timer类,Timer类就是对应一个超时任务,保存了超时时刻Timestamp,超时回调函数,以及超时任务类型(一次 or 周期)。接着讲解了如何在linux中实现定时,选择的定时函数,timerfd_* 系列函数的使用。最后到了管理多个定时的类TimerQueue。讲解了选择哪种数据结构来进行管理定时器。该类需要解决比较多问题,其类内部有三个容器,一定要清楚哪个容器是解决了哪个问题的。

2025-04-02 11:32:22 725

原创 14.主从Reactor+线程池模式,Connection对象引用计数的深入分析

这Connection的引用计数变化和前面提到的两个函数中的lambda表达式为什么使用值传递也就很好理解了。这一节的代码改动是很小的,很小的变化就可以组合成主从Reactor+thread pool模式,也很好理解。所以可以说这节最重要的是理解其Connection的引用计数的变化,通过画出的这个图和讲解,应该可以深入地理解其引用计数的变化了。

2025-04-02 10:35:55 800

原创 13.主从 Reactor 模式的实现

因为loop_可能在其他地方访问,而IO线程函数退出时,线程已经不能继续运行,代表IO线程EventLoop的loop_也就没有了存在意义。如果不清空,析构函数可能会导致重复调用loop_->quit(),让IO线程loop循环重复退出。

2025-04-01 18:34:59 744

原创 12.实现跨线程安全调用函数

上一节我们添加了线程池,可以把一些比较耗时的任务放到线程池中处理。而我们处理完成后,需要把数据发送给回客户端,而上一节中,是在线程池的某一线程中把消息发送的,不是在IO线程发送。这样是有点问题,首先,这样就会有两个线程去控制该socket(IO线程会监听该socket的读写,而线程池又通过send()函数去调用该socket),这不符合我们的要求的。。那么,我们该怎么解决这个问题呢。

2025-04-01 16:04:57 535

原创 11.实现单Reactor与线程池的结合

回想一下单单线程模式,其伪代码简单来说,其是一个while循环,通过handleEvent()回调函数来执行与用户的请求操作,若handleEvent()函数要处理的事情是比较耗时的操作,比如一些长时间的计算等等,那这样就会堵塞在channel[i]->handleEvent();这句代码中,就可能不能及时有响应。

2025-03-31 21:20:15 726

原创 10.完善 Connection 类,单 Reactor 单线程模式成型

Reactor就是核心类EventLoop,就是一个循环。简单点说,其实就是一个epoll,通过epoll_wait()函数来进行dispatch。黄色的read(),send()这些就是可以看成是Connection类。这样,基础的单Reactor的模型就形成了。这是一个重要的版本,之后的版本都是在这个基础上面添加内容的,例如需要使用多线程。

2025-03-31 20:03:15 817

原创 9.解析Muduo的Connection类

这里还是。

2025-03-31 19:31:36 949

原创 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 533

原创 7.从Server到Acceptor,优化Reactor模式的实现

在上一节中,我们实现了的核心结构,创建了一个Server类,并且注意到许多逻辑集中在这个类中。一个简单的服务器程序主要由两部分组成:一部分是accept(2),另一部分是(即 TCP 连接)。为了提高代码的清晰度和可维护性,我们可以将Server类的这些功能进行分离。首先,我们可以创建一个新的类,称为,专门处理建立连接的逻辑。

2025-03-31 11:27:00 751

原创 6.实现 Reactor 模式的 EventLoop 和 Server 类

在上一节中,我们添加了Channel类,这已经进入到开始实现。这时我们为添加到epoll上的文件描述符都添加了一个Channel。每个Channel都可以拥有自己的回调函数,即用户可以按照自己的想法去往epoll中注册事件,之后可以根据不同的事件类型调用指定的回调函数。但上一章节还没有实现增添回调函数和调用回调函数,这一节来完成其实现。

2025-03-31 10:52:43 952

原创 5.实现 Channel 类,Reactor 模式初步形成

通过这一节的修改,我们可以获得关于epoll返回的活跃的文件描述符的更多信息,添加了Channel类。按照上面的思路,我们可以把firstTime和fd构成一个结构体,之后就使用联合体epoll_data的ptr,不使用fd。那么我们可以把一个文件描述符封装成一个类,这个类里面有更多的关于这个文件描述符的信息,我们把他叫做Channel类,那就可以指向任何一块地址空间,也可以指向一个类对象,这就可以包含关于这个文件描述符的更多信息。data,这是一个联合体。,这不符合我们的要求的,这将在下一节中进行修改。

2025-03-30 15:40:07 730

原创 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 548

原创 3.使用epoll实现单线程并发服务器

多路复用:指可以同时监控多个网络连接,并在同一线程中处理这些连接。epoll在处理大量并发连接时,性能通常优于select和poll,特别是在连接数达到上万的情况下。epoll是Linux特有的特性,无法在其他操作系统上使用。

2025-03-26 15:04:42 950

原创 2.基于多线程的TCP服务器实现

在我们预想中,服务器端应该能够同时与多个客户端建立连接并进行网络通信。然而,在之前的代码中,服务器实现只支持单一连接,因为在处理连接时,主线程会被accept()read()或write()等方法阻塞,导致无法响应新的连接请求。为了解决这一问题,本文将介绍如何实现一个多线程的TCP服务器,让我们来一步步分析并构建代码。

2025-03-26 00:03:10 616

原创 1.基于TCP的简单套接字服务器实现

在本文中,我们将深入了解套接字(socket)及其在网络通信中的应用,特别是如何在服务器端创建一个基于TCP的简单通信框架。套接字是程序员进行网络通信的一组接口,主要分为客户端和服务器端。在这篇文章中,我们将重点关注服务器端的实现。

2025-03-25 23:00:24 694

原创 2. 套圈(分治)

扔圆环是一种游戏,玩家需要将平面圆环扔向一些玩具,所有被圆环围住的玩具都会得到奖励。在虚拟游戏场地中,每个玩具的位置是固定的,而圆环被精心设计,只能一次性围住一个玩具。如果一个点与圆环的中心之间的距离严格小于圆环的半径,那么该点就被圆环围住。对于每个案例,第一行包含一个整数N(2 <= N <= 100,000),表示场地中的玩具总数。接下来是N行,每行包含一个(x, y)对,表示一个玩具的坐标。输出 对于每个测试案例,以一行输出所需的虚拟游戏场地经理所需的圆环半径,精确到小数点后两位。

2023-12-17 12:28:02 425 1

原创 2. 皇后的控制力

我们对八皇后问题进行扩展。国际象棋中的皇后非常神勇,一个皇后可以控制横、竖、斜线等4个方向(或者说是8个方向),只要有棋子落入她的势力范围,则必死无疑,所以对方的每个棋子都要小心地躲开皇后的势力范围,选择一个合适的位置放置。如果在棋盘上有两个皇后,则新皇后控制的势力范围与第一个皇后控制的势力范围可以进行叠加,这样随着皇后数量的增加,皇后们控制的范围越来越大,直至控制了棋盘中全部的格子。

2023-12-16 23:02:36 682

原创 4. 无向图的各连通分支

输出每个连通分支的广度优先搜索序列(从连通分支的最小编号开始),不同分支以最小编号递增顺序列出。第一行为图的节点数n(节点编号0至n-1,0

2023-11-26 15:35:30 487

原创 3. 迷宫问题

迷宫有一个入口,一个出口。一个人从入口走进迷宫,目标是找到出口。阴影部分和迷宫的外框为墙,每一步走一格,每格有四个可走的方向,探索顺序为地图方向:南(下)、东(右)、北(上)、西(左)。输入:输入迷宫数组。第一行数据表示一个 n*n (n<=100)的迷宫;第二行开始的n行为迷宫数据。其中:0表示路,1表示墙,起点在左上角 <1,1> 的位置,终点在右下角 <n,n> 的位置。输出:若有解,输出从入口到出口的一条路径,否则输出 there is no solution!例(上图所示的迷宫数组)

2023-11-26 14:47:19 511

原创 1. 图的广度优先遍历

输入是图的顶点序列和边序列(顶点序列以*为结束标志,边序列以-1,-1为结束标志)。程序的输出为图的邻接表和广度优先遍历序列。本实验实现邻接表表示下无向图的广度优先遍历。

2023-11-25 16:16:32 153

原创 3. 快速排序

要求根据给定输入,按照课堂给定的快速排序算法进行排序,输出排序结果和median3的返回值。注:1,cutoff值为5,不足cutoff使用插入排序。2,输入、输出格式参见测试用例0。

2023-10-31 11:42:07 340

原创 2. 堆排序

实验要求:用堆排序算法按关键字递减的顺序排序。程序输入:待排序记录数(整数)和待排序记录(整数序列);程序输出:建堆结果和建堆后第一、第二次筛选结果。(注:待排序记录数大于等于3)

2023-10-31 10:37:17 160

原创 1. 折半查找

折半查找的查找过程:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。每条待查记录包含关键字项和其他项,如关键字项为15,其他项为该记录在查找表里的原序号4。对无序表的查找,还需要事先排列成有序表,再进行折半查找。输入:5 (记录的条数)各记录项:如 32 1输出:已按关键字排列好的非递减序列:如 (16 2)(20 5)(32 1)(35 3)(91 4)找不到时输出: error。

2023-10-31 10:22:23 130

原创 2. 计算WPL

根据哈夫曼树,我们可以为叶子节点分配相应的哈夫曼编码,使得编码长度短的更常见,这样可以有效地减少编码的总长度,达到数据压缩的目的。这里的带权路径长度就是叶子节点的权值与它到根节点的路径长度之积的总和。2. 在所有未构造二叉树的集合中选出两个权值最小的树作为左右子树,构造出一棵新的二叉树,同时这两个权值之和作为新的父节点的权值。以二叉树为例,叶子节点是没有子节点的节点,而根节点是最顶层的节点。1. 对每个叶子节点,计算根节点到该叶子节点的路径长度,即从根节点到叶子节点所经过的边的数量。

2023-10-24 11:09:29 1708

原创 1. 前缀码判定

请编写一个程序,判断输入的n个由1和0组成的编码是否为前缀码。如果这n个编码是前缀码,则输出"YES”;否则输出第一个与前面编码发生矛盾的编码。前缀码:任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀。每一个字符均不是其他字符编码的前缀,所以,输出:YES。编码11与前面的编码110的前缀,所以,输出:11。第2~n+1行为n个由0或1组成的编码。第1行为n(表示下面有n行编码)

2023-10-24 10:45:58 393

原创 AVL树(基本操作代码)

【代码】AVL树(基本操作代码)

2023-10-19 16:23:43 122

原创 3. 平衡二叉树

程序输入一个字符串(只包含小写字母),请按照字符的输入顺序建立平衡二叉排序树,并分别输出二叉树的先序序列、中序序列和后序序列,最后输出该二叉树向左旋转 90 度后的结构。

2023-10-17 21:32:51 423

原创 2. 排序二叉树

排序二叉树是指左子树的所有节点的值均小于它根节点的值,右子树的所有节点的值均大于它根节点的值,如下图是一棵排序二叉树。输入有一行,表示若干个要排序的数,输入0时停止。建立并中序遍历一个排序二叉树。和二叉树的中序遍历序列。

2023-10-17 21:22:10 411

原创 1. 树的建立与基本操作

程序的输入是一个表示树结构的广义表。假设树的根为 root ,其子树森林 F = ( T1 , T2 , … , Tn ),设与该树对应的广义表为 L ,则 L =(原子,子表 1 ,子表 2 , … ,子表 n ),其中原子对应 root ,子表 i ( 1

2023-10-14 10:17:09 514

原创 3.二叉树遍历序列还原

给出二叉树的中序遍历序列和后序遍历序列,编程还原该二叉树。第1行为二叉树的中序遍历序列。第2行为二叉树的后序遍历序列。二叉树的按层遍历序列。

2023-10-12 21:19:20 619

原创 Day08-面向对象

类的组成是由属性和行为两部分组成属性:在类中通过成员变量来体现(类中方法外的变量)行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)类的定义步骤:①定义类②编写类的成员变量③编写类的成员方法public class 类名 {// 成员变量变量1的数据类型 变量1;变量2的数据类型 变量2;// 成员方法方法1;方法2;

2023-10-08 16:53:40 108

原创 4.从中缀向后缀转换表达式

中缀表达式就是我们通常所书写的数学表达式,后缀表达式也称为逆波兰表达式,在编译程序对我们书写的程序中的表达式进行语法检查时,往往就可以通过逆波兰表达式进行。总之,左括号和指数运算符在中缀表达式转换为后缀表达式的过程中需要被特殊处理,它们需要优先级高于其他运算符,并在栈中保持相对应的位置,以确保后续的处理和计算的正确性。为了简化编程实现,假定变量名均为单个字母,运算符只有+,-,*,/ 和^(指数运算),可以处理圆括号(),并假定输入的算术表达式正确。(A 一 (B*C 十 D)*E) / (F 十 G )

2023-10-04 16:25:50 707

原创 1. 括号匹配

假设一个算术表达式中包含圆括号、方括号两种类型的括号,试编写一个判断表达式中括号是否匹配的程序,匹配返回Match succeed!,否则返回Match false!。例[1+2*(3+4*(5+6))]括号匹配(1+2)*(1+2*[(1+2)+3)括号不匹配。

2023-10-04 10:21:21 144

原创 2.出栈序列

每组数据中,第一行为两个个整数 n 和 m。n 表示需要依次从 1~n 入栈,m 表示这组数据有 m 个出栈序列需要判断,当 n=0 且 m=0 时停止。对每一个出栈序列,如果能正常出栈,输出Yes,否则输出 No。求解规定序列能否由入栈出栈操作得到。接下来有行,每行表示一个出栈序列。

2023-10-02 16:55:37 261

原创 Day05-循环高级和数组

数据类型 [] 数组名比如:int [] array。

2023-09-28 19:16:09 155

原创 2. 孤独的运货员

卸货的过程是:首先查看最外面的箱子是否标记着 X 标签,如果是,代表这是运送到 X 国的货物,则放到 A 平台上,如果不是,则把该货箱放到B平台货物队列的末尾,然后处理下一箱货。每天,货车和货运飞机都这样周而复始的运行着,直到有一天因为报酬的原因,分理中心的工人开始罢工。航空公司的货运飞机往返于各个国家和货物分理中心之间,分理中心的货物运送到各个国家,再将各个国家发出的货物送到分理中心。从第二行往后一共有 N 行,每行一的第一个数字代表该站 B 平台上货物的总数,之后的每个数字代表每箱货物运送到哪个站。

2023-09-26 21:21:39 351

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除