- 博客(38)
- 收藏
- 关注
原创 C++集群聊天服务器(5)——Model数据层代码框架设计
先看看新增的目录与源文件:之前的6个文件(ChatServer、ChatService、public.h、main.cpp)构建了一个高性能网络框架 + 业务分发解耦,但业务(login/reg)只是打印日志,没有真实功能。新增的5个文件(db.h、db.cpp、user.hpp、usermodel.hpp、usermodel.cpp)加入了数据持久化层,实现了真正的用户注册(把用户名、密码存到 MySQL 数据库,并返回自增 id)。
2026-01-25 21:57:24
826
原创 算法——【最长回文子串】
学习算法之前,我们先理清楚几个基础概念:回文串:正读和反读一样的串回文子串:原文的某个回文串最长回文子串:原串中最长的回文子串接下来,我们看看问题是什么:给你一个字符串 s,找到 s 中最长的 回文 子串。接下来我一共会讲解三种算法。
2026-01-25 21:56:47
954
原创 C++集群聊天服务器(4)——网络模块与业务模块
首先我对之前的目录做了一些优化,按照标准开源代码的形式(这个我在C++集群聊天服务器(2)中讲解过)进行了改善:接下来开始讲解这些文件中的代码以及他们之间的联系。
2026-01-22 21:37:29
845
原创 算法——【最大子数组和】
比如:数组长度为 n ,我们用 i 表示子数组起点,从0到 n-1 依次遍历,每固定一个 i 就让 j 从 i 遍历到 n-1 ,同时累加从 i 到 j 的和,每算一次就和当前最大值比较并更新最大值,直到 i 遍历完所有位置,这样所有连续子数组都被我们检查了一遍,最后得到的最大值就是我们要求的答案了。示例1中的最大子数组就是[4,-1,2,1]这一段,他的元素和是6,是所有子数组中元素和最大的,所以6就是这个问题的答案。核心思想:把大问题拆成小问题,然后小问题解决后再合并,最终得到大问题的答案。
2026-01-22 14:05:07
704
原创 C++集群聊天服务器(2)——CMake构建集成编译环境
使用简单方便,可跨平台,构建项目编译环境。尤其比直接写Makefile简单(在构建大型工程编译时,需要写大量的文件依赖关系),可以通过简单的CMake生成负责的Makefile文件。
2026-01-18 16:15:53
492
原创 C++集群聊天服务器(1)—— muduo网络库服务器编程
1.程序启动 → 创建 EventLoop(epoll)2.创建 ChatServer → 内部创建 TcpServer,并注册两个回调(连接、消息)3.调用 server.start() → 开始监听 6000 端口新客户端连接 → 触发 onConnection(打印 online)已有客户端发消息 → 触发 onMessage(打印并回显)客户端断开 → 触发 onConnection(打印 offline 并关闭)
2026-01-17 20:33:49
1294
1
原创 TCP和UDP的区别全面对比讲解
TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protocol,用户数据报协议)都是 TCP/IP 协议栈中传输层的核心协议,负责在主机之间为应用层提供端到端的通信。下面我将从相同点、是否面向连接、数据传输方式、是否可靠、传输效率、应用场景这六个方面展开详细讲解。TCP 提供可靠、有序、面向连接的字节流传输,适合对数据完整性要求高的场景,但开销大、延迟高;
2026-01-17 20:33:02
1080
2
原创 内联函数与宏定义的区别
我先大致讲一下内联函数与宏定义:内联函数是C++的函数特性,在编译阶段进行代码替换,兼具函数的语法安全和宏的执行效率;宏定义是预编译阶段的文本替换,无类型检查和语法分析,灵活但易引发问题。二者的核心差异体现在编译阶段、类型安全、作用域等多个维度。
2026-01-16 20:12:25
678
原创 程序CPU占用率较高,教你如何排查
定位到代码位置之后,接下来就是基于上面的问题进行分析,分析完之后进行纠正,纠正完再进行运行,看看有没有继续出现CPU耗时的问题,如果有继续去进行纠正。这里我们没有看到低效的算法,是因为在过程中我们已经运行了很长时间,这个代码早就运行结束了。top -H -p:特定进程所有线程的详细信息。top -c :显示进程完整信息。top -H:启动线程模式。top -p:指定进程。
2026-01-16 13:53:29
224
1
原创 工厂模式详细讲解
工厂模式是创建型设计模式的核心,核心思想是将对象的创建与使用分离:把对象创建的复杂逻辑封装在“工厂类”中,业务代码(调用方)只需通过工厂获取对象,无需关注对象的实例化细节(如构造函数参数、子类选择等)。它主要解决了“直接new对象导致的代码耦合、扩展困难”问题,同时让代码更符合开闭原则和单一职责原则。主要分为简单工厂、工厂方法、抽象工厂三种形式,适配不同的业务场景。
2026-01-15 20:58:12
694
原创 HTTP缓存机制详细讲解
本质:对于一些具有重复性的HTTP请求,他们请求得到的数据都是一样的,我么们可以把这对【请求-响应】的数据缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了。核心逻辑是客户端携带缓存标识向服务器验证资源是否更新,服务器返回“有效”则复用资源,返回“无效”则拉取新资源。(1) 代理服务器(如CDN):优先读取响应头的 s-maxage (单位:秒),仅对代理生效,优先级最高。(2) 客户端服务器:若响应头无 s-maxage,读取max-age(单位:秒),优先级次之。
2026-01-15 10:55:56
806
原创 快速了解MySQL索引(什么是索引,分类)
索引是数据库中加速查询的特殊数据结构,类比书籍的目录,通过在表的列上创建索引,能快速定位数据行,避免全表扫描。
2026-01-02 18:27:02
447
原创 Redis 悲观锁与乐观锁
答:避免误删锁问题。如果直接用 DEL 命令,可能出现:客户端 A 获取锁后超时,锁自动释放,客户端 B 获取锁,此时客户端 A 执行 DEL 会删除客户端 B 的锁。思想:悲观地认为每次操作数据都会发生并发冲突,因此在操作数据前,必须先获取锁,确保同一时间只有一个客户端能操作该数据,其他客户端需等待锁释放后才能执行。为了解决分布式场景下的并发冲突,Redis衍生出了悲观锁和乐观锁两种核心锁机制,二者的设计思路完全相反,适用于不同的并发场景。如果版本号不一致,说明数据已被修改,放弃当前更新或重试。
2026-01-02 18:10:51
1178
原创 C++智能指针从入门到精通全解析
智能指针所有权引用计数额外开销支持数组(C++17)适用场景核心缺陷auto_ptr独占(转移)无无否已弃用(C++17)悬空指针、不能用于容器unique_ptr独占(不可转移)无无是(需指定[])单个对象/数组、无需共享不能共享所有权shared_ptr共享有有是(需指定[])多对象共享资源循环引用、额外开销weak_ptr无(弱引用)无无否解决循环引用、观察对象存活不能直接访问对象。
2025-12-27 03:05:05
664
原创 TCP拥塞控制
在TCP/IP协议簇中,传输层的TCP协议以可靠性著称,而拥塞控制是TCP实现高效、稳定数据传输的核心机制。网络拥塞如同公路堵车,若发送方无节制的发送数据,会导致网络链路被占满、数据包延迟/丢失,最终陷入“重传-更拥塞”的恶行循环。本文将从拥塞控制的核心概念入手,层层拆解慢启动、拥塞避免、拥塞发生、快速恢复四大算法,帮助大家彻底掌握TCP拥塞控制的底层逻辑。慢启动通过指数增长快速试探网络容量;拥塞避免通过线性增长保持传输稳定性;拥塞发生通过降低cwnd缓解网络压力;
2025-12-24 21:38:03
998
原创 僵尸进程与孤儿进程详解:原理、危害及解决方案
子进程先于父进程退出,且父进程未调用 wait() / waitpid() 系统调用读取子进程退出状态时,子进程残留的 PCB 不会被内核释放,此时该子进程被称为僵尸进程。父进程先于子进程退出,且子进程仍在运行,此时该子进程失去了原父进程的管理,称为孤儿进程。僵尸进程和孤儿进程的产生,根源是父子进程生命周期不同步和父进程资源回收逻辑缺失;僵尸进程的核心危害是耗尽 PID 资源,解决关键是父进程主动回收或交由 init 接管;孤儿进程本身无害,仅需处理失控场景;
2025-12-24 02:07:06
438
原创 HTTPS 常用密钥交换算法解析
答:因为IoT设备算力弱、内存小:PSK无证书校验,握手仅2轮,计算量极小,更适合资源受限的设备;而ECDHE需要生成临时密钥对,计算成本相对更高。答:选ECDHE-RSA。理由:① 支持前向保密,安全性更高;答:因为SM2是我国自主研发的国密算法,符合《网络安全法》等国内合规要求,能避免国外算法的潜在后门风险,保障金融数据的国家安全。基于长期密钥的算法:依赖服务器长期公钥 / 私钥,无临时密钥,不支持前向保密。基于临时密钥的算法:使用一次性临时密钥对,支持前向保密。核心流程(前文重点讲解的算法)
2025-12-22 22:31:58
779
1
原创 HTTPS【密钥交换+证书校验】流程讲解
而RSA算法的会话密钥依赖客户端用服务器长期公钥加密的 Pre-Master Secret ,长期私钥泄露则历史会话可被破解。② 性能:椭圆曲线计算效率高,256位椭圆曲线密钥的安全性≈3072位RSA密钥,但计算成本更低,更适配高并发场景。答:长期私钥是固定不变的,若失窃,历史流量可被解密;以面试最高频的ECDHE-RSA算法为例(支持前向保密,现代主流方案),拆解密钥交换的底层逻辑,其他算法可类比推导。证书是服务器的“网络身份证”,由权威CA签发,客户端必须完成4步必验流程,校验失败则直接终止握手。
2025-12-22 22:01:39
1308
原创 彻底搞懂Redis的单线程架构:为什么单线程还能这么快?
放弃多核CPU的利用率,换来了“无锁、无切换、高简洁”;靠内存速度、I/O多路复用、高效数据结构,把单线程的潜力挖到极致。
2025-12-22 00:59:01
615
原创 MySQL事务隔离:彻底搞懂脏读/不可重复读/幻读
问题类型核心定义危害脏读事务A读取到事务B未提交的临时数据(事务B可能回滚)读取无效数据,导致业务错误不可重复读同一事务内,多次读同一行数据,结果不一致(被其他事务提交的修改覆盖)破坏事务内数据一致性幻读同一事务内,多次执行同一查询,结果集行数变了(被其他事务插入/删除数据)像“幻觉”一样,结果不可信。
2025-12-21 15:11:11
724
原创 MySQL索引核心:聚集索引与非聚集索引
在学习MySQL过程中,阅读到这样一段话:在 MySQL 中,B+ 树索引按照存储方式的不同分为聚集索引和非聚集索引。我就在想为什么要分为这两种,下面我就详细介绍这两者的联系、优缺点。
2025-12-20 21:59:35
1212
原创 MySQL存储引擎详解:特点、区别与应用场景
在MySQL中,存储引擎是负责数据存储、处理和保护的核心组件,不同引擎适配不同业务场景。本文将全面解析主流存储引擎的特点、差异及默认选择。
2025-12-19 00:25:32
407
原创 从疑惑到清晰:Linux与Windows的核心差异
作为计算机学习者或从业者,你是否也曾有过这些困惑:为什么市面上会同时存在Linux和Windows两大主流操作系统?先有的哪个?既然已经有了第一个,为什么还需要第二个?它们的核心区别到底是什么,该如何选择?带着这些问题,本文将从“诞生顺序”“核心差异”“存在意义”三个维度,用结构化的逻辑、通俗的语言,帮你彻底理清Linux与Windows的“前世今生”,同时突出关键重点,方便实际应用中参考。如果你是普通用户、办公人士、游戏玩家:优先选Windows,图形界面易用、软件生态完善,能满足日常所有需求;
2025-12-17 02:33:20
654
原创 一篇文章带你了解Redis数据类型
Redis作为高性能键值存储(缓存/数据库),其数据类型设计是“高性能+多场景适配”的核心,也是面试高频考点、业务开发必备技能。本文将分「核心数据类型」「拓展数据类型」两大模块,讲透每个类型的特点、常用命令、实战场景,并附加记忆技巧,帮你快速掌握~
2025-12-17 01:58:20
902
原创 C与C++核心区别深度解析笔记
C是“轻量、底层、过程式”的语言,适合追求极致控制的场景;C++是C的超集,兼顾底层控制与开发效率,适合复杂项目。理解两者差异,能帮你更合理地选择技术栈。
2025-12-11 01:12:25
405
原创 epoll全面解析:从用法到底层原理
适用场景高并发服务器(如 Web、网关、游戏服务器);大量连接但少量活跃的场景;追求高性能,低CPU开销的场景。选型建议场景推荐方案原因少量 fd(<50)select简单高效,无需额外内核资源中量 fd(<1000)poll无 fd 限制,比 select 省心大量 fd(>1000)百万级支持,O(1) 就绪遍历低延迟高并发epoll(ET模式)触发次数少,CPU 开销最低逻辑简单易维护epoll(LT模式)
2025-12-10 19:58:03
935
原创 poll核心指南:从用法到差异详细讲解
核心要点poll 是 select 的改进版,核心优势:无 fd 数量限制、无需重复初始化、遍历/拷贝开销更合理;核心数据结构 struct pollfd :通过“fd+events+revents”打包存储,解决了 select 中 fd 与事件分离的痛点;底层核心优化:动态链表管理监控集合、精准遍历、精准唤醒,解决了 select 的无效操作和惊群效应;
2025-12-09 13:54:42
771
1
原创 彻底吃透select:从用法到内核实现的完整指南
在网络编程中,I/O 多路复用是解决高并发的核心技术, select 作为最基础、跨平台的实现方案,是理解 epoll、kqueue 等高级机制的关键铺垫。很多初学者仅停留在“会调用函数”的层面,对其底层原理(如 fd 存储、内核检测逻辑、阻塞唤醒机制)一知半解,导致排查问题时无从下手。本文从【基础认知->核心用法->底层实现->流程串联->避坑指南】五个维度,用通俗语言+内核源码片段+精简示例,带初学者彻底吃透 select。核心要点。
2025-12-08 13:03:32
657
2
原创 C++ new/malloc、delete/free 深度解析:从基础区别到底层实现(超详细实战版)
本质区别: new / delete 管“对象生命周期”(构造+析构+内存), malloc / free 管“原始内存”(仅分配+释放);底层关联:默认全局 operator new / operator delete 依赖 malloc / free ,但可通过重载替换;使用原则:C++开发优先用 new / delete (符合RAII),仅C兼容/特殊场景用 malloc / free ,严禁混用;
2025-12-07 22:52:54
1187
原创 死锁深度解析:原理、场景、检测与解决方案(C++实践篇)
本文系统讲解了C++多线程编程中的死锁问题。首先明确定义了死锁及其四个必要条件(互斥、请求保持、不可剥夺和循环等待),分析了常见死锁场景如锁顺序不一致、递归锁不当使用等。然后介绍了死锁检测方法,包括资源分配图法、命令行工具和日志监控。重点阐述了三种解决策略:预防死锁(破坏必要条件)、避免死锁(银行家算法)和解除死锁(终止线程或资源剥夺)。最后给出了C++并发编程中的最佳实践建议,并区分了死锁与活锁、饥饿的区别。文章提供了可落地的解决方案,帮助开发者彻底解决死锁问题。
2025-12-07 13:35:39
760
原创 C/C++变量三兄弟:局部、静态局部、全局变量的区别+场景,一篇讲透
本文系统分析了C/C++中三类变量(局部变量、静态局部变量、全局变量)的核心特性与使用场景。通过定义位置和static关键字的组合,详细阐述了各类变量的作用域、存储期、链接属性、内存位置等关键差异,并提供了代码示例说明其初始化规则和线程安全性。文章特别强调编程时应遵循"最小作用域+最少共享"原则,优先使用局部变量,谨慎使用全局变量。最后通过对比表直观呈现三类变量的本质区别,为开发者提供清晰的变量选型指南。
2025-12-06 20:35:18
1488
原创 C++函数重载 vs 重写:从概念到底层实现,一篇搞懂
C++中的函数重载和重写是初学者容易混淆的两个概念。重载指在同一作用域内定义多个同名函数,通过参数列表(类型、个数、顺序)不同来区分,编译时根据实参确定调用哪个版本。重写则是子类对基类虚函数的覆盖,要求函数签名完全一致,运行时根据对象实际类型决定调用哪个实现,是实现多态的关键。 重载通过编译器名字修饰实现,每个版本会被赋予唯一内部名称。重写则依赖虚函数表和虚指针机制:每个含虚函数的类有一个虚函数表存储函数地址,对象通过虚指针访问该表,运行时动态确定要调用的函数版本。
2025-12-06 16:59:41
1550
原创 彻底吃透C++单例模式:从入门到面试(附代码+场景+陷阱)
摘要: 本文系统讲解C++单例模式的实现演进与核心要点。首先提出单例模式的三大设计原则:私有构造函数、禁止拷贝/赋值、静态全局访问点。随后分析5种典型实现方案:饿汉模式(简单但浪费内存)、非线程安全懒汉模式、加锁保护的线程安全版、双重检查锁定(DCL)优化版,以及C++11推荐的局部静态变量实现(工业级最优解)。特别强调线程安全与内存序问题,指出std::atomic对避免指令重排的关键作用。最后探讨单例析构问题,对比不同方案的资源释放机制,提供动态分配下的嵌套析构类解决方案。
2025-12-05 11:19:03
528
原创 虚拟内存详细讲解——分页篇
本文系统阐述了内存管理的分页机制及其演进。分页通过将内存划分为固定大小的页(如4KB)解决了分段机制的外部碎片和交换效率问题,但引入了内部碎片。核心机制是虚拟地址到物理地址的页表映射,但单级页表占用空间过大,多级页表通过分层索引节省内存,TLB缓存则缓解了多级查询的性能损耗。进一步介绍了段页式管理,结合分段逻辑优势和分页效率,但需三次内存访问。文章以具体数值示例解析地址转换过程,对比了不同机制的优缺点,完整呈现了内存管理技术的演进脉络。
2025-12-04 15:22:45
1097
1
原创 虚拟内存详细讲解——分段篇
程序按逻辑功能拆分为多个“段”(如代码段、数据段、栈段、堆段),每个段有独立属性(权限、用途),通过“分段机制”将这些段在内存中分离管理,实现程序逻辑与物理内存的解耦。举个生活例子:把程序比作“书包”,分段就是把书包里的物品按功能分类装袋:- 栈段=装临时草稿纸的袋(随用随丢);- 堆段=装备用文具的袋(按需取用);- 数据段=装笔记本的袋(可写,记录内容);- 代码段=装课本的袋(只读,不能乱涂);每个袋(段)有独立的存放区域,互不干扰。
2025-12-04 13:51:51
729
1
原创 指针基础知识
我们平常说的指针,通常指的是指针变量,是用来存放内存地址的变量;指针的大小是固定的4个字节或8个字节,取决于你的操作系统(32位/64位)。下面交大家如何使用指针:变量有不同的类型,如整形、浮点型、字符型等;指针也有类型,对应其指向的变量类型。 1.指针+-整数代码示例:运行结果: 指针的类型决定了指针向前或者向后走一步有多大(距离)。比如:int* 指针+1,意思是跳过一个整型,也就是向后走4个字节;char* 指针+1,意思是跳过一个字符型,也就是向后走1个字节;short* 指针+1,意思是跳过一个短
2024-05-08 16:21:03
482
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅