自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 TCP、UDP1

要**解决粘包和拆包问题,是上层应用层协议应该做的事情,**比如HTTP协议,当服务器需要通过TCP连接接收HTTP请求报文的时候,会按照请求行、请求头、请求体三个状态解析HTTP报文,如果一次读取多个报文,那就解析出多个HTTP请求。第三次握手避免了这种情况的发生:如果有一个留在网络中的SYN过期报文,服务器接收到了之后,完成握手,但是此时的客户端并没有要和服务器建立连接,服务器单方面ESTABLISHED(连接就绪),但是实际上这个连接只会白白占用服务器资源不做事。变的就是源IP和源端口。

2026-07-23 00:28:28 271

原创 HistoFind搜索引擎

之前的正倒排索引,存放了文档的全部内容,正排索引的数组和倒排索引的哈希表。同样,待会构建索引的时候,是直接整个url,content,title,和哈希表直接放进内存,而据了解,大型的搜索引擎系统,由于内容太过庞大,所以内存里存的是正排倒排索引具体内容在硬盘中的地址。想要支持不停机更新,就要维护两个索引(放弃之前的单例设计模式),在内存中同时存放两个索引,一个索引用来给searcher实时读取,另一个索引用来在新数据到来的时候写入,比如一个新的网页到来,解析出。所以为了查到的数据天然有序,建立一个(

2026-07-22 01:31:19 228

原创 nextLoop高并发服务器组件

上面的的内容已经告诉我们,一个Connection对象构造初始化的时机是监听套接字事件到来,调用TcpServer传入的NewConnection回调,构造一个连接对象,设置它的各种事件回调,然后启动超时销毁和将自己添加到Poller监控。因为连接绑定了EventLoop,EventLoop又绑定一个定时器对象,所以自然可以通过EventLoop找到定时器对象,将连接销毁的回调函数传给定时器对象,让定时器对象析构的时候调用这个回调函数。设置这个对象的析构函数中的回调函数(将这个id的从哈希表中移除)。

2026-07-22 01:30:44 192

原创 HTTP、HTTPS2

服务器发证书,客户端校验时:直接用私钥加密证书太大,先哈希得到指纹再加密这个指纹,然后客户端同样哈希算一遍这个证书得到指纹,再用公钥解密服务器传来的加密指纹。客户端随机公钥私钥,服务器随机公钥私钥,证书公钥(客户端),证书私钥(服务器)。SSE和WebSocket的核心区别在于,SSE是单向(服务器到客户端),WebSocket是全双工的。特点:全双工,客户端发完消息不用等回复,服务器也可以随时推送数据。无HTTP头部冗余。服务器发送证书,用私钥签名,客户端用证书公钥验证签名,证明服务器确实有这个私钥。

2026-07-19 04:54:17 407

原创 HTTP、HTTPS1

为了解决TCP的队头阻塞问题,HTTP/3.0采用了基于UDP的QUIC协议,复用TLS协议握手,连接建立加快,只重传丢失的包,实现流级别的多路复用,使用连接ID标识一个连接,切换网络能复用原连接。引入长连接,允许一个TCP连接上发送多个请求和响应,但是必须按照顺序发送和接收,所以在HTTP层存在队头阻塞(一个请求处理很慢,接下来的请求只能排队等待)HTTP基于TCP还是UDP要视版本而论,如果是HTTP1.0、1.1、2.0,那么是基于TCP的,如果是HTTP3.0,是基于UDP实现的QUIC协议。

2026-07-19 02:27:49 264

原创 Linux操作系统1

用户态和内核态本质上是CPU在执行进程的指令时的不同状态,当进程执行的指令只访问用户空间定义的数据,不涉及对操作系统管理的资源的操作时,就是用户态,当执行的指令访问操作系统空间定义的数据或者访问操作系统管理的资源(文件、硬件、内核数据结构等)时,就是内核态。操作系统在单个CPU核心上,通过时钟中断,不断减少一个进程的时间片,直到时间片耗完,标志位设为1,返回用户态前检查标志位,如果为1就触发软中断,执行进程调度中断处理。或者硬件触发,比如键盘触发,比如之前等待在IO事件的休眠进程被唤醒,抢占CPU。

2026-07-16 03:04:28 330

原创 C++基础1

从设计哲学上来说C语言是“信任程序员”,而C++是“不为无用之物买单”,C语言追求的是极致的透明和控制,C++追求的是保证高性能的同时还通过RAII和多范式提供强大的抽象能力。,申请空间后手动初始化内存。注意到,引入列表初始化后,习惯使用直接列表初始化而不是复制列表初始化,这是因为某些情况下,比如unique_ptr的构造函数,不允许进行隐式类型转换 explicit修饰。列表初始化,旨在提供一种统一的初始化方式,从内置类型、自定义类型到STL容器,都可以使用列表初始化**{}**的方式进行初始化。

2026-07-13 17:27:38 215

原创 C语言笔记17:编译和链接

预先定义好的有固定意义的符号__FILE__ //源文件名,比如test.c__LINE__ //源文件当前的行号__DATE__ //被编译的日期__TIME__ //被编译的时间__STDC__ //编译器是否遵循ANSI C标准__TIME__表示的是被编译的时间,而不是运行到本行的时间,所以要打印日志,不能使用__TIME__而是应该使用一些运行时函数,比如time()。

2026-01-10 18:03:57 347

原创 C语言笔记16:文件操作

scanf读取内容其实是在缓冲区中读取,比方说输入abcd\n,缓冲区的内容就是abcd\n,如果以%s的形式输入,就会省略\n,\n会被留在缓冲区里面,如果以%c形式输入,则有可能读取到\n。标准输入输出流是向终端打印文本信息,使用二进制输入输出可能会产生一些意想不到的后果,比如换行符的解释不同,以及一些控制字符的问题。我们刚刚使用的输出接口是fputs,这是一个专门用于字符串输出的接口,它和fprintf一样,属于**专门用于字符输出的,它们的共同点在于不会将。**那所以SEEK_END指向的位置是。

2026-01-10 18:03:19 713

原创 C语言笔记15:动态内存管理

开辟失败返回NULL传入0标准未定义。

2026-01-10 18:02:05 493

原创 C语言笔记14:结构体、联合体、枚举

内存对齐是拿空间换时间的做法,CPU每次访问的地址都是4字节(32位)或者8字节(64位),并且变量的起始位置也是4或8字节的倍数,结构体内部遵循了内存对齐的规则之后,CPU想取出结构体内的int或者double这种类型的变量,就不会面临一个int横跨两个4字节或者8字节块的情况。联合体内一个大的成员变量和一个小的成员变量,小成员变量使用联合体的内存时和数组一样,是从低地址到高地址使用的,可以利用这个特点来判断机器的大小端。(16位机器最⼤16,32位机器最⼤32,写成27,在16位机器会 出问题。

2026-01-10 18:01:07 328

原创 C语言笔记13:数据在内存中的存储

当一个数据比如short类型等,大小超过一个字节,就会有字节序的问题。

2026-01-10 18:00:22 982

原创 C语言笔记12:C语言内存函数

这个参数,因为它不是对字符串操作,没有默认的终止位置。目标空间和源空间有重叠的情况是未定义的。内存函数和字符串函数的区别大致都在于。,以及内存函数都带有。

2026-01-10 17:59:04 295

原创 C语言笔记11:字符函数和字符串函数

不能自己拼接自己,想要自己拼接自己,可以定义一个临时缓冲区。就是一个字符分类函数,用来判断一个字符是不是小写字母。perror(“描述信息”),打印被设置的全局变量。函数返回str2在str1中第一次出现的位置。打印错误码对应的错误信息,这些信息一般存在。一样都是右边赋值给左边返回初始地址空间。到目标空间并将原来的\0修改。看一个字符分类函数的用法。strcat模拟实现。最多比较num个字符。描述信息:错误信息。

2026-01-10 17:58:05 519

原创 C语言笔记10:sizeof和strlen,指针与数组

这里粗心了一下,把strlen(p+1)算成6了。这里的坑是一维数组是使用圆括号初始化的。地址是一个无符号整数。

2026-01-10 17:56:32 292

原创 C语言笔记9:指针

数组名是数组首元素地址不假,但是arr的类型是int [10],&arr的类型是int(*) [10]。有了指针变量类型,指针±整数的时候跳过的地址数就由指针变量的类型决定。指针解引用访问指向的空间修改字节数,和修改的方式也由指针变量的类型决定。右边是不同的效果,放在左边表示解引用操作不能修改指针指向的空间,放在右边表示指针不能进行±整数的操作了。str1,和str2是栈上的不同字符数组的首元素地址,而str3和str4则指向静态区的只读数据段。&a取出来的地址是存放a的四个字节中,地址较小的那个。

2026-01-10 17:55:02 668

原创 C语言笔记8:操作符

打个比方说,如果long 的大小是4字节而不是8字节,它无法表示所有的unsigned int 类型,所以long 会转换成 unsigned int 这是因为无符号数和有符号数相互运算时,如果占字节数相同,那优先将有符号转成无符号。打个比方说,如果long 的大小是4字节而不是8字节,它无法表示所有的unsigned int 类型,所以long 会转换成 unsigned int 这是因为无符号数和有符号数相互运算时,如果占字节数相同,那优先将有符号转成无符号。对于整型数据,内存中存放的都是补码。

2026-01-10 17:52:43 948

原创 C语言笔记7:函数递归与函数栈帧

递归即为递推和回归,是一种解决问题的办法。在C语言中体现为函数自己调用自己。

2026-01-10 17:51:47 922

原创 C语言笔记6:调试

当程序中出现问题的时候,找问题并消灭问题的过程叫做调试,debug。

2026-01-10 17:50:41 350

原创 C语言笔记5:函数

ret_type fun_name(形参) {.h文件声明函数和全局变量.c文件定义函数和全局变量。

2026-01-10 17:49:22 568

原创 C语言笔记4:数组

初始化数组时,编译器会按照给的元素个数和初始化方式给数组(不仅仅是二维数组)分配对应大小。数组大小一旦确定就不能更改,变长数组的意思是,确定数组大小的时机从编译时变成了运行时。C99标准引入了变长数组的概念,当创建数组的时候,可以给数组元素个数里放一个变量。C99标准引入了变长数组的概念,当创建数组的时候,可以给数组元素个数里放一个变量。在C语言笔记2:C语言数据类型和变量中一张图中提到,数组是一种自定义类型。下标从小到大,依次打印数组元素的地址。数组是一组相同类型元素的集合。[ ]:内表示数组元素个数。

2026-01-10 17:47:41 735

原创 C语言笔记3:分支与循环

2026-01-10 17:45:54 386

原创 C语言笔记2:C语言数据类型和变量

C语言提供了不同的数据类型,编译器根据数据类型的不同,对一块数据进行不同的操作,比方说:对一个浮点数类型的数据进行加法运算和对一个整数类型的数据进行加法运算,其运算过程是肯定不一样的。但是在我看来,其实内置类型只有整型和浮点类型两大类,字符型和布尔类型只不过是特殊的整型而已。

2026-01-10 17:42:11 614

原创 C语言笔记1:C语言常见概念

标识符不能和关键字冲突externstatic。

2026-01-10 17:37:39 766

原创 学习使用typora

快捷键:ctrl + t 创建表 ctrl + enter 快速插入一行 ctrl + shift + 删除键 快速删除一行 tab 键快速跳到下列。可能在其他电脑上不显示。//按回车键默认是将区块延伸,上下键退出区块,如果有什么都没写,回车键是将当前行的区块删除。还是不要直接在网页粘贴链接好,这是为了可移植性考虑,缩放之后,就自动变成了html的语言。ctrl + 数字 ,ctrl + (‘+’ || ‘-’).快速对文本级别做修改。试着输入1 * 2 * 3 * 4 解决*不显示的问题。

2025-12-15 20:21:45 901

原创 排序算法:快排的深入优化和文件归并

cur从left+1的位置开始找,当cur处于的位置的值小于key的值时,交换cur和left的值,然后left和cur都+1,当cur所处位置大于key值时,交换cur和right的值,right-1往前找。最后file1中存放的就是排序好的数据。这样的然后再递归排序left以左的数据,和right以右的数据,这样的设计方法很好的避免了重复数据过多的时候,快速排序算法时间复杂度退化的情况。一趟这样的循环的最终结果就是,left指向了一段相等数的最左边的值,right指向了一段相等数的最右边的值。

2025-07-11 01:00:04 1372

原创 数据结构笔记10:排序算法

第一趟插入排序是先让end的值为0(表示[0,0]位置的值是有序的,也就是第一个数据有序),取end后一位的值插入到[0,end]这个有序序列之中,如果tmp的值小于end的值,就让end往前,找到更小的值。选择排序比较好理解,这里就不画图了,唯一需要注意的一点是,交换最小值和头位置再交换最大值和尾位置的逻辑,如果头位置存放的是最大值的话,此时把它和最小值的位置交换,下次尾位置交换最大值的时候找到的就不是原来的最大值,而是最小值了,所以这里需要判断一下。一趟排序将最大的值交换到末尾,然后接着下一趟排序。

2025-07-10 16:27:17 868

原创 数据结构笔记9:二叉树

长文预告。

2025-07-09 01:50:15 965

原创 数据结构笔记8:堆

一棵深度为 kk 的满二叉树,是指所有。

2025-07-06 17:09:53 1190

原创 数据结构笔记7:栈和队列应用、循环队列等

我们想象两个管道,每次都会留下其中一个管道是空的,然后入数据入非空的那个管道,出数据的时候先将有数据的那个管道的数据转移到另一个空的管道。2.a、当head和tail下标一直往后更新,迟早会到数组的边界,当tail或者head下标到了数组尾(下标为k的位置),此时它们的下一个位置应该是0。所以想用队列实现栈就是让每次删除队列元素的时候删除队尾的元素,然而队列并不提供删除队尾元素的方法,所以我们就要使用两个队列来实现逻辑上的删除队尾元素。当删除元素的栈空了时,可以将接受元素的栈的数据交换到删除元素的栈中。

2025-07-04 14:47:25 452

原创 数据结构笔记6:栈和队列

当使用顺序表形式来实现栈的时候,由于顺序表底层采用数组的形式,当缺少某个数据时,CPU会预取这个位置的数据以及这个位置后面的一片数据进入缓存。当下一次需要读取数据时,发生缓存 命中的概率就会提高。如果一个数据被访问了,那么它在不久的将来很可能再次被访问。只有在栈大小变化极大(可能极大或极小)时,考虑链表实现。如果一个数据被访问了,那么它附近的数据也很可能被访问。:每次push需要分配新节点,pop需要释放节点。:链表节点在内存中不连续,导致缓存命中率低。:循环中的变量、栈顶元素(频繁的。

2025-07-01 19:05:51 860

原创 数据结构笔记5:环形链表的数理分析

使用快慢指针的方法:当慢指针和快指针相遇的时候证明链表是有环的。证明:假设环的长度为C,入环前的长度为L。假设fast在环内走了n圈。,fast和slow的距离为2L-n*c-L = L-n*C。由于fast每次走两步,slow每次走一步,所以fast和slow之间的距离每次缩小一个单位。当slow距离第一个入环的节点的距离为(n+1)*C-L时,fast和slow会相遇。

2025-06-30 23:28:14 424

原创 数据结构笔记4:数组、链表OJ

为了实现这种深拷贝,先在原链表的每个节点后面创建一个值和原来节点一样的节点(就形成了一种原来节点下一个节点是拷贝节点的结构),然后再遍历这些新节点,让它们的random值指向原来节点的random值的下一个节点。第二种方法则更加巧妙:利用异或的性质(相同数字异或为0,0和任何数异或都为其本身),先异或从0到n的所有数字,再异或数组的所有数字,剩下的就是消失的数字。首先判断两个链表是否相交,相交链表的最后一个节点一定相等,不相交链表的最后一个节点一定不等。方法一:先找出链表节点个数,再返回倒数第k个节点。

2025-06-29 22:49:10 431

原创 数据结构笔记3:双向链表

是因为使用原来的方法需要传入的参数是二级指针,破坏了接口的统一性,为了使方法的使用成本更低,所以把初始化方法调整成这样的形式。当链表只剩下一个节点时,我们进行删除操作不需要修改头结点,只需要将头结点指向的next指针和prev指针指向自己。这使得当链表为空时,我们进行插入操作不需要修改头结点,只需要将头结点指向的next指针置为新节点。像是对单链表的尾插,当链表为空链表(头结点为空时),就需要修改头结点的值,让新的节点成为头结点。双向链表的指定位置的插入和删除不需要遍历链表找指定位置前的节点。

2025-06-27 21:36:43 310

原创 数据结构笔记2:链表

创建一个新的头结点(头结点可能要删除)并和原来的头节点相连,对链子进行操作,(从指向头结点的链子开始遍历),如果是要删除的节点,就修改指针指向下一个节点,如果不是要删除的节点,就更新cur为下一个节点的链子。cur从头结点开始,外层循环走n-1次,内层循环走m-1次,更新cur的值和prev的值,内层循环每结束一次就修改prev指针的指向,删除cur节点,再更新cur为next。修改指向指定位置的指针,释放调指定位置的节点(这个删除逻辑无法处理指定位置为头节点的情况),当指定位置为头节点的时候,进行头删。

2025-06-27 19:48:08 900

原创 数据结构笔记1:顺序表

顺序表就是一个进行了封装的数组,对这个数组有各种已经实现好的增删查改的方法,方便使用者使用。在插入、删除操作时,操作数据的位置不同,需要移动的数据个数也不一样。由于底层是数组,所以可以实现随机访问(知道下标的前提下)。同时插入还需要扩容检查,容易造成空间浪费和时间消耗。

2025-06-27 14:59:24 231

原创 C语言:实现贪吃蛇小游戏

正文开始这是一个网页版本的贪吃蛇小游戏,可以看到一开始打印了一个欢迎界面,选择难度后进入游戏,难度越高,蛇移动的速度越快,左下角还有一个积分的数字。今天我们使用C语言在命令行窗口上实现以下这个简单的贪吃蛇小游戏。打开vs,创建两个源文件test.c和snake.c,分别表示测试逻辑的代码,和贪吃蛇游戏真正实现的代码,再创建一个snake.h头文件,用来表示贪吃蛇游戏的函数声明以及一些结构体的定义和头文件的包含。在测试逻辑中,我们简单的将游戏的逻辑分成了GameStart(),GameRun(),GameEn

2025-05-17 00:37:32 612

原创 C语言实现扫雷小游戏的相关拓展

假设我们要排查的坐标是(1,1),并且以一行一行的顺序检索(1,1)坐标周围的雷数同样为0的点,那么在函数在递归的过程中,我们发现(1,2)的位置周围的雷数也为0,所以我们再进入函数判断(1,2)点的周围是否存在周围雷数为0的位置的时候,我们发现(1,1)的位置周围雷数为0。我们想到能使用函数的递归,我们知道,递归的思想就是把一个复杂的问题一步步拆分成一个简单的问题:那么当我们想要自动展开一个周围雷数为0的位置x1,其实就是要先把x2,x3的位置自动展开,然后再展开x1。

2025-04-24 14:40:15 543

原创 简单扫雷小游戏的实现

分析:首先,扫雷游戏要有一个9*9的棋盘,上面所有的符号都显示为*,在*字符的背后,有些放置了雷,而有些没有放置雷,没有放置雷的地方,我们会打印出它周围八个格子存在的雷的数量,假设我们定义#为雷其他地方存放数字,那打印出来棋盘的时候,肯定会直接把数字和#打印出来,而不是打印*,这样游戏就不用玩了。在我们的分析中,mine数组一共有两种数据,一种是雷,另一种是周围存在雷的数量,为了统计某个格子周围八个格子存在雷的数量,我们考虑到棋盘周边的格子可能会出现越界访问的情况,所以将棋盘设计成11*11的更大的数组。

2025-04-09 20:14:45 288

空空如也

空空如也

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

TA关注的人

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