- 博客(40)
- 收藏
- 关注
原创 【项目日记(二)】
我们的这个高并发服务器是可以支持各种不同的协议,我们进行协议支持的时候,socket有数据到来了,我们去接收数据的时候,缓冲区中的数据不足一条完整的请求,或者比一条完整的请求多。我们就得考虑将socket缓冲区中的数据进行处理,那么数据处理到一半的时候,就得考虑在下次数据到来的时候继续处理,因此,我们就需要给服务器中的每一个连接都设置一个协议处理的上下文,专门用来控制请求数据接收和处理的节奏的。2、上下文的类型不能固定,因为服务器支持的协议可能会不断增多,不同的协议,可能会有不同的上下文结构。
2025-04-16 14:50:54
483
原创 【项目日记(一)】-仿mudou库one thread oneloop式并发服务器实现
客户端处理思想:事件驱动模式事件驱动处理模式:谁触发了我就去处理谁。( 如何知道触发了)技术支撑点:I/O的多路复用 (多路转接技术)1、对所有客户端进行IO事件监控、哪个客户端触发了事件,就去处理谁处理:接收它的请求,进行业务处理,进行响应。优点:单线程操作,操作都是串行化的,思想简单,(不需要考虑进程或者线程间的通信问题,以及安全问题)缺点:所有的事件监控和业务处理都是在一个线程中完成的,因此很容易造成性能瓶颈适用场景:客户端数量较少,且业务处理快速简单的场景2、
2025-04-15 13:52:35
610
原创 【Linux高级IO(三)】Reactor
这种方式避免了服务器一直阻塞在等待新连接的操作上,服务器可以在等待新连接的同时处理其他任务,提高了资源利用率和程序的响应速度。函数可以被多个不同的监听套接字复用,只要这些套接字需要处理新的客户端连接。函数主要负责将套接字添加到事件监听机制中,并为不同的事件类型注册相应的回调函数,它专注于事件的管理和调度。回调函数,服务器可以高效地处理这些连接请求,而不会因为某个连接请求的处理而阻塞其他连接的接受。函数则专注于处理新的客户端连接,包括接受连接、创建新的套接字、设置新连接的属性等操作。
2025-04-08 21:32:11
620
原创 【Linux高级IO(二)】初识epoll
1、向上交付 2、将数据交付给tcp的接收缓冲区 3、查找rb_tree, 看fd,并且看有没有关心EPOLLIN或者EPOLLOUT 4、如果有,构建就绪节点,插入到就绪队列中。返回值是一个文件描述符,创建一个struct file结构体,指向epoll模型,返回的是在进程文件描述符表中的一个fd,通过这个fd就能找到epoll模型。这意味着tcp会向对方通告一个更大的窗口,从而从概率上让对方一次给我发送更多的数据!2、就绪队列(双链表)某个节点的事件就绪了,就将他链入就绪对列中。
2025-04-07 21:04:19
791
原创 【Linux高级IO(一)】理解五种IO模型
1、应用层read&write的时候,本质把数据从用户写给OS ---- 本质就是拷贝2、IO = 等待 + 拷贝(大部分时间在等待,等到有数据了才进行拷贝)要进行拷贝,必须先判断条件成立。这个条件就是读事件就绪,就是读缓冲区有足够的数据可以读 写事件就绪就是发送缓冲区中要有足够的空间什么叫做高效IO呢?单位时间内,IO过程中,等的比重越小,IO效率就越高!其实几乎所有提高IO效率的策略,本质就是让等的比重变小。
2025-04-01 19:22:33
910
原创 【Linux网络(七)】数据链路层
5、NAT技术。1、认识MAC地址Mac地址用来在同一个局域网中,区分特定的主机。1、MAC地址用来识别数据链路层中相连的节点;2、长度为48位, 及6个字节. 一般用16进制数字加上冒号的形式来表示(例如: 08:00:27:03:fb:19)3、, 不能修改. mac地址通常是唯一的(虚拟机中的mac地址不是真实的mac地址, 可能会冲突;也有些网卡支持用户配置mac地址).MAC地址 像身份证号(唯一标识设备硬件),IP地址 像邮寄地址(逻辑定位网络位置)
2025-03-27 20:09:50
943
原创 【Linux网络(六)】网络层协议 IP协议
目录1、IP报头2、网段划分3、IP地址数量限制4、私有IP和公有IP5、路由IP协议的本质工作:提供一种能力,将数据跨网络从A主机送到B主机! 可是有能力不一定能确保每次都能成功。这就需要传输层提供策略和网络层提供能力,两者相结合,确保成功!8位服务类型:3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0). 4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本. 这四者相互冲突, 只能选择一个. 对于ssh/telnet这样的应用程序, 最小延时比较重要; 对于
2025-03-27 10:57:56
996
原创 【Linux网络(五)】传输层协议
客户端在三次握手中,认为只要把三次握手中第三次报文发出,就认为连接建立好了。万一第三次报文c已经发出了,可是s并没有收到,这时c就认为连接已经建立成功了,可是s却认为连接,没有建立成功。这时c向s发送一次数据,s就会向c发送携带RST字段的报文,告诉c连接建立失败,要重新建立连接。
2025-03-26 09:45:42
801
原创 【Linux网络(三)】网络基础套接字
socketTCP是面向连接的 ,服务器一般是比较”被动“的,服务器要一直处于一种,一直等待连接到来的状态。就需要进行监听socketr第一个参数: socket 刚刚打开的,并且已经设置为listen状态的套接字文件描述符建立连接(TCP,客户端)
2025-03-18 18:01:46
460
原创 【Linux网络(二)】网络基础套接字
意思就是TCP协议在发送数据时, 不管一次性发送多少数据, 也不管数据一共要发送几次,它只关心能尽快的将数据从客户端发送到服务器. 所以说TCP在发送数据时, 完整的数据可能是: “abcdefg123456"但是第一次可能发送了"abcdefg1”,第二次再发送"234",再发送"56". 这都是不定的. 而UDP是面向数据报的, 它每次发送数据时, 会将完整的数据全部保存在一个报文中, 然后将这个数据报整体发送过去。1、网络协议中的下三层,主要决定的是,数据安全可靠的送到远端机器。
2025-03-16 17:16:13
943
原创 【Linux网络(一)】初识网络
网络其实就是进程间通信的一种,跨网络通信是在不同主机上进行的(比如在西安要访问qq,而qq的服务器进程可能在深圳),而通信的复杂程度是和距离成正比的。在网卡出厂时就确定了, 不能修改. mac地址通常是唯一的(虚拟机中的mac地址不是真实的mac地址, 可能会冲突;交换机---划分碰撞域 任何主机都可以向局域网中发数据,但是任何时刻只允许一台主机向局域网中发数据,避免碰撞。长度为48位, 及6个字节. 一般用16进制数字加上冒号的形式来表示(例如: 08:00:27:03:fb:19)
2025-03-10 21:00:15
613
原创 【Linux】多线程---线程池(3)
池化技术是指提前准备一些资源,在需要时可以重复使用这些预先准备的资源。其实就是线程池在线程池启动时就创建多个线程来备用,同理,对象池和内存池也就是创建多个对象/空间备用。提高性能。通过重用资源,减少了创建和销毁资源的时间,从而提高了资源的使用效率降低系统开销, 避免了频繁地向操作系统申请和释放资源的开销简化代码。通过封装资源管理逻辑,使得应用程序代码更简洁易。
2025-03-10 08:53:54
616
原创 【Linux】多线程---生产者消费者模型(2)
生产者消费者模型的本质就是通过一个阻塞队列来将生产者和消费者解耦合的模型.可以将这个模型比作一个超时,生产者生产了数据(商品)后,不会直接拿给消费者使用,而是将数据(商品)先加入到超市,让超市帮我们卖数据(商品).同理,对于消费者来说它并不会直接去生产者的厂家直接拿数据(商品),而是去超市中购买数据(商品).这样生产者和消费者两个对象就解耦合了。
2025-03-06 21:08:58
848
原创 【Linux】多线程(1)
什么是线程?线程是操作系统调度的基本单位。什么是进程?内核观点:进程是承担分配资源的基本实体如何理解我们以前的进程?操作系统以进程为单位,给我们分配资源,我们当前的进程内部,只有一个执行流!!复用数据结构和管理算法,struct task_struct ---------Linux没有“真正”(只是没有像Windows一样设置struct tcb)意义上的线程,而是用“进程”(进程的内核数据结构)模拟线程。
2025-03-05 15:28:23
735
原创 【Linux】进程信号
当捕捉到信号之后,将默认动作变为了自定义动作。(ctrl+c就不会退出了)键盘数据是如何输入给内核的,ctrl+c又是如何变成信号的键盘被按下,肯定是OS先知道的!OS怎么知道键盘上有数据了??linux下一切皆文件,因此键盘也是文件。读取键盘数据就是将键盘数据读取到键盘文件的缓冲区中。那么OS如何知道键盘中有数据了??数据层面上,CPU是不和硬件打交道的。但是在控制层面,CPU是要能读取外设的。
2025-02-27 13:48:38
847
原创 【每日一题】
假如要将奇数放在数组前面,偶数放在数组后面,就可以最左边放一个指针(left)最右边放一个指针(right) 如果是不满足前后条件的,就交换left与right。因此,如果我们将每一类的元素全部异或起来,那么其中一类会得到 x1,另一类会得到 x2这样我们就找出了这两个只出现一次的元素。** 归并排序(Merge Sort)** 是建立在归并操作上的一种有效、稳定的排序算法。,表示空字符串可以通过任何字典拆分(即没有字母是需要拆分的)。,并确保合并后的数组仍然按非递减顺序排列,我们可以利用。
2025-01-07 16:25:07
877
原创 【Linux】动静态库
1、制作静态库之前对动静态库的认识:libXXX.a-----静态库静态链接:将库当中的代码拷贝到最终的可执行程序里,也就是,自己的源代码会变成.o,将我用过的代码考到我的可执行程序里,从此我就不用再依赖这个静态库了。libYYY.so------动态库动态链接:是产生关系,调用这个库函数的地址填进去就好了gcc默认是动态链接 库的名称是去掉前缀去掉后缀把我们提供的方法给别人用:1、把源代码直接给他 2、把我们的源代码打包成库 就相当与头文件+库 给他库里面的文件
2024-11-11 11:40:34
756
原创 【Linux】文件系统
删一个文件的时候,拿到文件编号,到inode Bitmap里找到文件的inode编号,看它的位图是1说明他是有效的,然后再去inode Table读取它的属性,获得对应的块的块号,在Block Bitmap中将所有块号全部清零,然后再去inode Bitmap里将对应的清0,就完成了文件的删除。每一个inode都有自己的inode编号(inode的设置,是以分区为单位的,不能跨分区) inode表示文件的所有属性,文件名,并不属于inode内的属性。那么,我们怎么知道一个文件的inode编号?
2024-10-30 21:14:40
858
原创 【Linux】基础IO-上
1、文件 = 内容 + 属性2、文件分为打开的文件和没打开的文件3、打开的文件是谁打开的?答案是:进程!---本质是研究进程和文件的关系文件被打开必须先被加载到内存,一个进程可以打开多个文件。因此,在OS内部一定存在大量被打开的文件。OS要管理这些被打开的文件--先组织,再描述---再内核中,一个被打开的文件必须有自己的文件打开对象,包含文件的很多属性。struct XXX{文件属性;对打开文件的管理就是对链表的增删查改。4、没打开的文件:在哪里放着?我们最关注什么问题?
2024-10-24 21:49:28
746
原创 【Linux】进程控制
当我们要想自己对代码区进行写入时,OS会对我们的行为进行拦截,但是现在我们调用的是系统函数,对代码区进行写时拷贝的工作是由OS来完成的,因此,是可以的。c语言调用库函数不成功的时候,返回值告诉我们这个函数的情况,结果对不对,至于结果不对的原因,比如当库函数调用失败了,C语言就会将我们的errno全局变量设置成对应的数字,这个数字表示我们。上面代码的现象:前5s子进程运行,运行5s,子进程变为僵尸状态,父进程运行5s子进程此时还是僵尸进程,之后,父进程回收子进程,然后僵尸进程没有了,父进程单独运行5s。
2024-10-22 19:13:21
695
原创 c++进阶----map和set
更新后parent平衡因子 ==1 or -1,说明parent所在的子树高度变化,会影响祖先,需要沿着root的路径往上更新---------(继续执行1、2)更新后parent平衡因子 ==2 or -2,说明parent所在的子树高度变化且不平衡,对parent所在子树进行旋转,让它平衡 -----(插入结束)更新后parent平衡因子 ==0,说明parent所在的子树高度不变,不会再影响祖先,不用再继续沿着root的路径往上更新------(插入结束)同上两个指针,小的就是差集,小的++;
2024-09-29 20:08:14
1140
原创 C++进阶--异常
class Exception //基类public:,_id(id){}protected:int _id;class SqlException : public Exception //sql类public:{}return str;private:class CacheException : public Exception //cache模块public:{}return str;
2024-09-23 14:24:30
801
原创 C++进阶--二叉树进阶
请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。4、InOrder不需要返回值的原因:只需要在原树上对指针的指向进行改变,就好了,而且不需要在此函数中拿到头节点。在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。、最多查找高度次,走到到空,还没找到,这个值不存在。,统计成功后,给定单词就可快速找到其出现的次数,,通过英文可以快速找到与其对应的中文,英。,或者是具有以下性质的二叉树。
2024-09-19 15:48:36
709
原创 C++进阶--多态
多态的构成条件:1、必须通过基类的指针或者引用调用虚函数。2、调用的函数必须时虚函数,且派生类必须对虚函数进行重写(三同:函数名,返回值类型,参数类型)public:virtual void BuyTicket() const {cout
2024-09-06 13:09:39
733
原创 C++进阶--继承
以前我们接触的复用都是函数复用,继承是类设计层次的复用。继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许在保持原有类特性的基础上及逆行扩展,增加功能,这样可以产生新的类,称为派生类。1.1定义格式派生类 继承方式 基类1.2继承基类尘缘访问方式的变化1、基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,只是语法上限制派生类对象不管在类里面还是在类外面都不能去访问它。
2024-09-04 18:09:37
957
原创 C++模板进阶
优点:模板复用了代码,节省资源,更快的迭代开发,c++的标准模板库(STL)因此而产生增强了代码的灵活性缺点:1.模板会导致代码膨胀问题,也会导致编译时间变长2.出现模板编译错误时,错误信息非常凌乱,不易定位错误。
2024-09-03 20:58:04
890
原创 STL---stack和queue
1、stack是一种容器适配器,专门用在具有后进先出操作的上下文换进中,其删除只能从容器的一端进行元素的插入与提取操作。2、stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供了一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。3、stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类因该支持以下操作:empty:判空操作back:获取尾部元素操作push_back:尾部插入元素操作。
2024-09-03 16:52:02
983
原创 STL----list
1、list是可以在常熟范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。2、list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。3、list(双向)与forward_list(单向)非常相似,最主要的不同在于forward_list是单链表,只能向前迭代,以让其更简单高效。4、与其他序列式容器相比(array, vector, deque), list通常在任意位置进行插入、移除元素的执行效率更好。
2024-06-13 15:42:48
726
原创 STL--vector
1、vector是表示可变大小数组的序列容器2、就像数组一样,vector也采用存储空间来存储元素,也就意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。3、本质讲,vector使用动态分配数组来存储它的元素。当新元素插入的时候,这个数组需要被重新分配大小。为了增加存储空间,其做法是,分配一个新的数组,然后讲全部元素移到这个数组。
2024-06-05 21:19:08
1133
原创 C++模板初阶
class 类模板名//类内成员定义//动态顺序表//注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具public:,_size(0){}//使用析构函数演示:在类中申明,在类外定义~Vector();//注意:类模板中函数放在类外进行定义时,需要加模板参数列表if(_pData)
2024-05-24 16:17:55
964
原创 C/C++内存管理
new的原理1.调用函数申请空间2.在申请的空间上执行构造函数,完成对象的构造delete的原理1.在空间上执行析构函数,完成对象中资源的清理工作2.调用函数释放对象的空间new T[N]的原理1.调用函数,在中实际调用函数完成N个对象空间的申请2.在申请的空间上执行N次构造函数delete[]的原理1.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理2.调用释放空间,实际在中调用来释放空间。
2024-05-23 19:13:33
652
1
原创 C++初阶--类和对象
1、声明和定义全部都放在类体中,但是需要注意的是如果在类中定义,编译器可能会将其当成内联函数处理。2、类声明在.h文件中,成员函数定义放在.cpp文件中。但是在.cpp中要在成员函数前面加*一般情况下推荐第二种。
2024-05-23 12:18:31
915
原创 C++入门
1.1为什么???使用命名空间的目的是对标识符进行本地化,避免命名冲突或名字污染。1.2怎么做???命名空间的定义:*命名空间是可以嵌套*同一个工程中允许存在多个相同名字的命名空间,编译器最后会自动合成一个。ps:一个工程中的test.h和test.cpp中的相同名字的命名空间会合并成一个。命名空间的使用:法一:命名空间名+作用域限定符法二:使用using将命名空间中某个成员引入法三:使用using namespace 命名空间名称 引入3.缺省参数是函数在声明或定义时为函数
2024-05-15 21:54:14
929
原创 指针和数组习题解析
sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小。&数组名,数组名表示整个数组,取出的是整个数组的地址1除此之外,所有的数组名都是数组首元素的地址。
2023-08-27 12:58:42
40
原创 指针进阶
int *p110intp2)[10//p1, p2分别是什么?p1是一个整形指针数组,数组里面存放了十个整形指针。p2是一个数组指针,指向的是一个大小为10个整形的数组//这里要注意:[]的优先级要高于号的,所以必须加上()来保证p先和结合。
2023-08-21 00:37:37
48
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人