自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 高并发内存池项目

这个项目是一个高并发内存池项目,其原型是 Google 的一个开源项目 TCMalloc,其全称为Thread Caching Malloc,即线程缓存的 malloc,旨在提供高效的多线程内存管理,可以用它替代语言提供的内存分配相关的接口 (malloc、 free)。学习和理解 TCMalloc 最核心的框架设计,并模拟实现一个 mini 版的高并发内存池。

2024-06-17 16:45:49 906 1

原创 协议的认识和理解

对于协议,我们可以用一句话概括它:协议本质上就是一种约定。

2024-09-08 12:39:01 923

原创 C++ 11 --- 中

如果我们不写,编译器会自动生成一份,而对于它们俩也不例外,但是,以前的默认成员函数,只要我们不写,编译器就会自动生成一份,例如,我们不写构造,那么编译器就会自动生成一份构造,然而,移动构造和移动赋值自动生成的条件却更为苛刻。也就是说,看似移动语义的自动生成条件很苛刻,但是如果一个类没有资源需要清理,那么就可以满足移动语义的自动生成条件,反之,如果有资源需要被清理,那么移动语义不会被自动生成。我们无法直接获取参数包 args 中的每个参数的, 只能通过展开参数包的方式来获取参数包中的每个参数。

2024-05-17 17:07:02 927

原创 C++11 --- 上

列表初始化对于内置类型来说,用的相对较少;但是对于自定义类型,特别是 STL 的容器,还是很有意义的。简单的理解:可以被取地址的对象,都被称之为左值;反之,不能被取地址的对象,称之为右值。在C++中,左值(L-value)是可以被标识符引用的表达式或对象,它具有持久性并且可以被修改。通常,变量、对象、数组元素和函数返回的左值引用都被认为是左值。左值可以取地址并且可以对它赋值。左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。

2024-05-17 16:52:09 923

原创 布隆过滤器

布隆过滤器优点:增加和查询元素的时间复杂度为:O(K),(K为哈希函数的个数,一般比较小),与数据量大小无关;哈希函数相互之间没有关系,方便硬件并行运算;布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势;在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势;数据量很大时,布隆过滤器可以表示全集,其他数据结构不能;使用同一组散列函数的布隆过滤器可以进行交、并、差运算。

2024-05-16 21:51:34 1016

原创 位图的实现和应用

对于无符号整型来讲,其范围是0 至 2^32-1,那么我们也就需要2^32个位即可,也就是 2^29 个字节,而我们知道 2^30 是1GB,那么 2^29 个字节也就是512MB,相较于上面的思路,节省了很大的空间。它将每一个位(0 或 1)映射到一个特定的索引位置,如果位为1,那么说明映射到这个位的Key是存在的,反之如果位为0,那么说明这个Key是不存在的。与上面的思路一致,同样用两个位图(去重),将文件的数据 set 到两个位图中,遍历两个位图,如果相同位置的位 == 1,则是交集。

2024-05-16 21:38:06 954

原创 哈希表的理解和实现

在闭散列中实现哈希表时,我们所用的哈希表的初始大小为10,且后续扩容是以2倍的方式进行的,但我们在直接说过,由于除留余数法存在哈希冲突,故为了减少哈希冲突,人们发现,如果表的大小为一个素数,就会减小哈希冲突的可能。具体的操作是,如果哈希表中的某个槽位已经被占用,则线性探测会依次检查下一个槽位,直到找到一个空闲的槽位,然后将元素存储在该位置。为了克服线性探测的缺点,还有其他的解决冲突方法,如二次探测等,二次探测,缓解线性探测的 "踩踏" ,在实际运用中,可以根据具体的场景和需求选择适合的解决方案。

2024-05-15 21:30:36 1113

原创 红黑树的理解和简单实现

因为如果新增节点是黑色,那么一定会违反红黑树的规则,反之,如果是红色,则可能插入之后不违反任何规则,因此我们将新增节点设置为红色。g --- grandfather(祖父节点 ), p --- parent(父节点) ,u --- uncle(叔叔节点),c --- cur(新增节点)。,继续判断,如果符合前面的条件(p、u为红)继续向上更新,最后为了避免不同的情况,将根节点的颜色更新为黑即可。思路: 只要某节点是红色的,那么只要判断它的父亲即可,如果父亲是红色的,那么就不是红黑树,反之,则符合红黑树。

2024-05-12 17:35:45 1157

原创 map 和 set 的介绍和简单使用

原因是,operator[] 通常用于直接访问容器中特定键 (Key) 对应的值 (Value),而对于 std::multimap 这种允许一个键关联多个值的容器来说,使用 operator[] 并不明确应该返回哪个值 (Value),此时的 operator[] 的行为就变得模糊不清。最后,(*((this->insert(std::make_pair(k, mapped_type()))).first)).second 取得插入的键值对中值 (Value) 所在的部分,即当前插入的键所对应的值。

2024-05-12 17:17:58 624 1

原创 AVL 树的理解和简单实现

这样可以提供更好的性能和效率。旋转处理的情况分为四种:左单旋、右单旋、左右双旋、右左双旋;旋转的原则:旋转后仍是一颗AVL树;旋转的目的:左右均衡,降低整棵AVL树的高度。

2024-05-12 17:17:34 728

原创 二叉树进阶 --- 中

相信前两个过程是没有困难的,最后一步可能不好实现,但是当我们经过了前两个过程,我们发现被删除节点变成了我们找到的"合适节点",而且这个"合适节点"很有特征,如果它是左子树的最大值,那么它一定不会有右子树,反之,如果他是右子树的最小节点,那么它一定不会有左子树。由于 root 是4的右孩子的引用,且 root 的右孩子为空,那么root = root->_left,就可以将4的右孩子由6变更为5,我们在删除6即可,因此我们需要提前保存6节点,当指向变更之后,delete 6。找到合适位置,创建节点并连接。

2024-05-11 21:29:11 912

原创 二叉树进阶 --- 上

假如现在我们要删除4所在的节点,可以发现,4所在的节点有两个孩子,因此无法托孤,那么我们需要采用替代法删除,替代法删除就是在左子树或者右子树找一个"合适节点",将4所在的节点的key进行覆盖,将删除4所在的节点转化为删除我们找的这个"合适节点"。同时,我们发现,最后进行托孤法删除时,我们也进行了判断,这样的原因是因为这个"合适节点"既可能是父节点的左孩子,也可能是父节点的右孩子,因此必须判断。如果被删除节点是父亲节点的左孩子,那么在这里就是父亲节点的左孩子指向被删除节点的非空节点。

2024-05-11 21:29:06 923

原创 C++ 多态的相关问题

赋值运算符重载可以是虚函数,因为调用赋值的两个对象是已经存在的对象,既然已经存在的对象,如果有虚函数,那么虚表的指针是被初始化过了的,也就是说赋值运算符重载可以进入虚表,虽然赋值运算重载可以是虚函数,但是赋值运算符重载实现多态是没有实际价值的。首先,派生类 B 继承 A类,会将B类的方法继承下来,但注意,继承是派生类有访问基类方法的权限,而并不是说基类的方法在派生类中也有一份,继承后的基类方法依旧属于基类;清楚了这个问题 ,接下来就简单了,之前说过,初始化列表的初始化顺序是由继承的先后顺序决定的。

2024-05-10 17:46:06 835

原创 C++ 多态 - 下

可以看到,无论以上面的任一方式,最后调用的 Func1()是一定的 (都是 Derive::Func1 ),只不过不同的调用可能会做一些封装 (为了处理不同的情况)。具体解释:首先:这里存在很多编译器的行为,比如我们打印的地址事实上并不是函数 (Derive::Func1) 的真实地址(即函数的第一条指令的地址),而是一个跳转指令 (例如这里的 jmp 指令 ) 的地址,跳转指令会跳转至函数真正的执行语句。但是我们依然可以理解为虚表中存储的是虚函数的地址!

2024-05-10 15:15:28 1330

原创 C++继承 - 下

很多人说 C++ 语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,也不建议设计出菱形继承,否则在代码维护以及性能上都有问题;多继承可以认为是 C++ 的缺陷之一,很多后来的oo(object--oriented) 语言都没有多继承,如 Jave;继承和组合:public 继承是一种 is-a 的关系。也就是说每个派生类对象都是一个基类对象;组合是一种 has-a 的关系。

2024-05-07 17:24:00 866

原创 list 的模拟实现

首先,在 string 和 vector 的模拟实现中,我们也使用过迭代器,但是它们两个的迭代器很特殊,因为它们存储的元素的地址是连续的,因此,它们的迭代器本质上就是原生指针,那 list 这里能不能也是原生指针呢?lt {1, 2, 3, 4},通过 it 拷贝构造得到 copy, copy {1, 2, 3, 4},copy 遍历一遍,每个元素 *= 2,即 copy {2, 4, 6, 8},那么此时 lt 是什么呢?可是我们发现一个问题,这咋遍历呢?这两个函数构成函数重载吗,答案,构成,为什么呢?

2024-05-05 19:30:50 862

原创 vector 的模拟实现

经过对比我们得知,造成这种问题的愿意就是因为发生扩容后,_start、_finish、_end_of_storage的值发生了改变 (因为是新空间),而pos还是在扩容之前的位置上,那么接下来的while循环也就没有意义了,进程崩溃也就可以理解了;但是对于某些类来说,编译器默认生成的拷贝构造是不符合需求的;原因是因为这是值传递,形参的改变不影响实参,因此在这里的 pos 依旧是失效的(当发生扩容时),因此我们得出的结论就是当插入了数据,不要再访问这个pos了,因为我们不能万无一失确保pos的有效性;

2024-05-04 17:24:30 977

原创 string 的模拟实现

字符串最后一个单词的长度_牛客题霸_牛客网 (nowcoder.com)string str;// 此处用 cin 不会通过测试用例if(pos!else。

2024-05-04 14:44:52 894

原创 DNS、ICMP、NAT以及代理服务器

域名是用来识别主机名称和主机所属的组织机构的一种分层结构的名称。如 www.xxx.com,域名使用 . 连接:www: 是一种习惯用法 (可以省略 ),之前人们在使用域名时,往往命名成类似于 ftp.xxx.xxx / www.xxx.xxx 这样的格式,来表示主机支持的协议;xxx: 二级域名,一般是公司或者组织的名称;com:一级域名,表示这是一个企业域名,同级的还有 "net" (网络提供商)、"org" (非营利组织)、"edu" (教育机构) 等等。

2024-05-02 17:21:10 1441

原创 LeetCode LCR 179. 和为s的两个数字

如果是第一种情况,因为数据是有序的,且left是当前范围 [left, right] 最小的数据,最小的数据 + right (66) 都大于了目标值 (61),因此,66 这个值就可以排除了,即 right 向左移动;如果是第二种情况,因为此时 right 是当前范围 [left, right] 中最大的数据,最大的数据 + left 都小于目标值,因此,left 当前位置的数据就可以排除了,故 left 向右移动;假设数据为 [8, 21, 27, 34, 52, 66],目标值为61;

2024-05-01 21:35:58 523

原创 LeetCode 15. 三数之和

2.2. 双指针 + 单调性

2024-05-01 21:35:27 959 1

原创 LeetCode 611. 有效三角形的个数

a = 4, b = 6, c = 9,a + b > c,成立,因为在a到b这个区间中,a此时是最小的,而数据又是单调递增 (有序的),因此,在 a 和 b 中间的值就不需要再判断了,此时一定可以和 b = 6,c = 9 构成三角形,因此,此时可以构成三角形的个数:b的下标 - a 的下标,b向左移动。而 a + c > b 和 b + c > a 不需要判断,因为此时c是最大的数据,最大的数据加上一个非负数,一定大于另外的一个数据,比如,a + c 是一定大于 b 的。2,3,4 (使用第一个4)

2024-04-30 16:31:23 1403

原创 网络层 --- IP协议

众所周知,网络传输是有一定概率丢包的,如果分片了,对于接收端网络层而言,它必须收到所有的分片,只要丢了其中的某一个,这次传输都是失败的 (需要重传),所有分片都会被丢弃,因此,分片实质上是增加了丢包概率,也正因为如此,操作系统内部是不愿意作分片的,体现上就是传输层的MSS,但是,我们知道,在跨网络传输中,会经过不同的设备,而不同的设备的MTU可能不一样,因此,分片行为在所难免,但是传输层的MSS可以避免频繁分片的情况。一旦支付完成,运营商会激活用户的互联网服务,允许路由器访问互联网;

2024-04-29 15:03:01 1129

原创 数据链路层

最后再补充一点,尽管TCP有MSS,通信时,双方主机也会协商MSS的值,但是,由于不同设备的MTU是不一样的,因此,数据在跨网络传输中,经过不同的设备 (MTU不一样),也会存在数据分片的情况,但是,MSS 能在很大程度上减少分片的可能,进而在一定程度上,提高了网络传输效率和稳定性。因为,此时要对IP数据报进行封装,即添加MAC帧报头,源MAC地址很好获得,就是路由器C的MAC地址, 可是目的MAC地址是主机B的MAC帧地址,但是,此时路由器C不知道,它只知道主机B的IP地址,不知道主机B的MAC地址。

2024-04-29 14:51:34 611 1

原创 Reactor 模式

总结: Reactor服务器是一种常见的网络服务器架构,通常用于处理大量并发连接和请求。事件轮询:Reactor服务器采用了事件驱动的架构模式,其中包括一个主事件循环(Event Loop),负责监听和派发事件;多路复用:Reactor服务器通常使用多路复用技术来监听多个I/O通道的事件。这样可以在单进程中同时处理多个连接,提高服务器的性能和吞吐量;事件处理器:Reactor服务器通过事件处理器来处理不同类型的事件。每个事件处理器通常负责特定类型的事件,例如获取连接、读取数据、发送数据、异常事件等。

2024-04-22 23:14:28 1147

原创 LT 和 ET 模式

李四此时还有王五的一个快递,但李四就再也不主动联系王五了,这时,张三路过,告诉李四,我这里还有一个王五的快递,你帮我给他送了吧,李四说,行,此时李四就有两个快递了,(快递个数发生变化了),于是李四才联系王五说,有两个快递,下来取,不来我就走了,王五此时还在打决赛圈呢,但王五啥也不管,立刻直接放弃比赛,来到楼下,把剩下的两个快递取走了, 这是李四。李四拿了三个快递,来到了王五的楼下,给王五打电话📞,告诉王五,快递到了,快下来取快递,如果你不下来,我就走了 (只打一次电话,即只通知一次)。

2024-04-21 21:20:28 686

原创 IO多路转接之epoll

上面这一整套机制,我们就称之为 epoll 模型。当上层调用 epoll_create 时:体现在内核层上就是,构建红黑树、就绪队列、回调机制;当上层调用 epoll_ctl 时:对这颗红黑树进行操作 (增删改),比如增加,体现在内核就是,增加一个特定文件描述符关心的事件;

2024-04-18 21:57:07 1018

原创 IO多路转接之poll

poll 的优点:IO效率高:因为 poll 服务器可以一次性等待多个套接字就绪,而IO过程 = 等待事件就绪 + 拷贝数据,而 poll 会将多个套接字的等待时间进行重叠,换言之,在单位时间内,poll 服务器等待的比重是比较低的,因此,它的IO效率就高;有适合 poll 的应用场景:当有大量的连接,但只有少量连接是活跃的。因为 poll 服务器是单进程的,因此,对于 poll 服务器的维护成本非常低 (不需要维护过多的执行流),哪怕有非常多的连接,poll 服务器的成本也微乎其微,即节省资源。

2024-04-16 18:05:20 756

原创 IO多路转接之select

nfds:这个参数指定文件描述符集合中所有文件描述符的范围,其值是最大文件描述符值加 1。这是因为 select() 需要知道需要检查的文件描述符的数量范围。除开第一个参数 (nfds) 之外,后四个参数都是输入输出型参数。select 可以同时等待多个文件描述符,等待策略是可以选择的,通过 timeout 这个参数:如果 timeout 为 nullptr, 代表阻塞等待;如果 timeout 是 {0, 0},那么代表非阻塞等待;

2024-04-16 18:05:13 659

原创 Linux --- 高级IO

冯诺依曼体系:站在冯诺依曼体系的视角,从输入设备读取数据到存储器,这个过程就是Input;而将存储器的数据写入到输出设备,这个过程就是Output;因此,IO本质上就是访问外设的过程。因为外设相较于内存、cache缓存、寄存器、CPU的速率是比较低的,故IO的效率是比较低的,尤其涉及到网络,效率问题就更加突出。张三的钓鱼方式:阻塞式;李四的钓鱼方式:非阻塞轮询式;王五的钓鱼方式:信号驱动;赵六的钓鱼方式:多路转接 (或多路复用);田七的钓鱼方式:异步IO;这五种方式,我们称之为五种IO模型。

2024-04-16 18:05:03 679

原创 传输层 --- TCP (下篇)

TCP主要是为了保证传输可靠性,但也在效率和其他方面做了努力。可靠性:校验和序号和确认序号确认应答按序到达去重连接管理超时重传流量控制拥塞控制提高性能:滑动窗口快速重传延迟应答捎带应答其他:定时器(比如超时重传定时器,保活定时器,TIME_WAIT定时器等)

2024-04-05 14:09:14 1071

原创 传输层 --- TCP (上篇)

我们知道,TCP 协议是面向字节流的, 因此我们可以将 TCP 协议的发送缓冲区看成一个 char buffer[NUM] 的字符数组,而上层将数据拷贝到发送缓冲区中,实质上就是拷贝到这个字符数组中,而我们知道,数组有一个天然的属性,就是数组下标,这里的数组下标就可以作为每一个数据的编号,即序列号。TCP自身无法判定数据段和数据段的边界,也不提供数据段整体的大小信息。同时,由于序号的存在,接收方收到数据后,在向上交付时,可以根据序号来进行排序,让上层得到的数据是有序的, 这种机制我们称之为按序到达。

2024-04-05 14:09:10 1445

原创 传输层 --- UDP

因为UDP协议用的端口号是16位的,而UDP协议是基于操作系统的,而操作系统提供了一系列的系统调用接口(比如socket接口)来支持网络通信,应用层通过这些接口与网络进行交互,因此,为了与UDP协议和操作系统保持一致,应用层需要使用16位的数据类型来定义端口号。

2024-04-05 14:09:06 2405

原创 探究 HTTPS 的工作过程

加密: 将明文进行一系列变换,生成密文;解密: 将密文进行一系列变换,生成明文;在加密和解密的过程中,往往需要一个或者多个中间数据,辅助这个过程,这样的数据我们称之为密钥。数据摘要也称之为数字指纹, 其基本原理是利用单向散列函数 (Hash函数) 对信息进行运算, 生成一固定长度的数字摘要。数字摘要并不是一种加密机制, 因为, 如果是加密,那么必然要有解密,而哈希是无法逆推的,一旦对原始文本经过 Hash 形成数据摘要, 很难 (几乎不可能) 根据数据摘要逆推原始文本;

2024-03-26 21:04:24 2450

原创 HTTP --- 下

上面的过程大致是相同的,只不过提交表单的方式不同罢了, 但为了更好地理解,我们可以画一下图,形象的描述下这个过程:因为,在我们的测试中,服务端的默认首页就是表单,因此,客户端通过IP:Port就能访问到服务端的默认首页,也就是表单,表单收集用户的数据,并将数据以特定的方式 (GET、POST) 传递给服务端。GET方式,是将表单数据附加到HTTP请求的URL中传递给服务端。由于数据明文添加在 URL 中,因此用户输入的信息会在 URL 中回显,不够私密,适合传输一些不敏感的数据。POST方式,

2024-03-24 16:27:37 1126

原创 HTTP --- 上

HTTP 协议本质上是一个文本协议,因为它采用文本格式来进行请求和响应的传输和通信,同时从 HTTP 请求和响应的结构也可以看出,它们都是由文本数据组成的,各种属性和信息也以文本形式呈现;域名后的第一个 "/" 我们称之为 Web 根目录, 这个目录一般是由服务端自定义的,它代表着服务端资源的起始地址,是客户端访问服务端资源的入口路径;未来,服务端的各种资源都可以放在这个路径 (Web根目录) 下,并通过特定的 URL 来访问这些资源。

2024-03-22 21:54:31 1058

原创 JSON 的了解和使用

使用 Json::StyledWriter::write 函数,你可以将 Json::Value 对象中的 JSON 数据转换为易于阅读的字符串,以便于输出、保存或传输。因为我们需要在 C++ 中解析和生成JSON数据, 因此我们需要安装 jsoncpp库, 用于处理JSON数据, 它提供了一组简单的API,可以方便地解析JSON字符串、生成JSON字符串以及在C++对象和JSON之间进行转换。Json::Reader::parse 是一个函数接口,用于将 JSON 字符串解析为 C++ 中的数据结构。

2024-03-17 23:26:53 1918

原创 序列化和反序列化

如上就是我们自己写的一个应用层代码,目前我们解决了三个问题:序列化和反序列化;定制了自己的协议;将我们的服务守护进程化, 让它变成一个网络服务;

2024-03-17 14:36:56 921

原创 套接字编程 --- 三

答案是:当然不影响咯, 因为进程具有独立性 (独立的地址空间、文件描述符表等等), 会以写实拷贝的方案保证自己的独立性。

2024-03-11 21:22:41 710

原创 套接字编程 --- 二

事实上,demo2 和 套接字编程 --- 一 中的 demo1只有在服务端处理数据不同罢了。demo2中是将客户端的数据当成了命令行字符串处理, 借用 popen 达到命令行解析、执行命令 or 进程,并将处理结果写入管道。服务端通过返回的文件指针读取管道内容,并将数据写回客户端。popen 本质上是调用了 fork 和 pipe ,因此,popen处理完毕后,使用 pclose 函数来关闭文件指针并等待子进程结束。

2024-03-10 10:47:59 1008

空空如也

空空如也

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

TA关注的人

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