- 博客(35)
- 收藏
- 关注
原创 LT模式和ET模式
如果服务端写的代码是阻塞式的read, 并且一次只 read 1k 数据的话(read不能保证一次就把所有的数据都读出来, 参考 man 手册的说明, 可能被信号打断), 剩下的9k数据就会待在缓冲区中。但是在 LT 情况下如果也能做到每次就绪的文件描述符都立刻处理, 不让这个就绪被重复提示的话, 其实性能也是一样的。如上面的例子, 虽然只读了1K的数据, 缓冲区还剩1K的数据, 在第二次调用 epoll_wait epoll_wait 的时候, epoll_wait 不会再返回了。
2025-02-18 19:14:18
248
原创 代理和NAT多路转接
a.静态地址NAT:静态NAT是一种一对一的地址映射方式,将内部网络中的私有IP地址直接映射到一个固定的公网IP地址,具有每个内部地址都固定映射到一个外部地址且适用于需要从外部网络访问的内部服务器的特点。a.从应用上讲, NAT设备是网络基础设备之一, 解决的是IP不足的问题. 代理服务器则是更贴近具体应用, 比 如通过代理服务器进行翻墙, 另外像UU这样的加速器, 也是使用代理服务器;c.从使用范围上讲, NAT一般在局域网的出口部署, 代理服务器可以在局域网做, 也可以在广域网做, 也可以跨网;
2025-02-18 00:13:24
980
原创 socket套接字
在计算机网络中,每一个通信都是通过两个独立的套接字进行的,一个是客户端的套接字,另一个是服务器的套接字。在TCP/TCP/IP协议的四层模型中,它是第四层即传输层的应用接口。TCP是有连接的,面向字节流的可靠传输;domain:指定通信域,常用有:AF_UNIX/AF_LOCAL(unix7),AF_INET(ipv4),AF_INET6(ipv6/7)。传输层协议(TCP和UDP)的数据段中有两个端口号, 分别叫做源端口号和目的端口号,就是在描述 "数据是谁发的, 要 发给谁"。
2024-10-23 23:03:53
431
原创 初入Linux网络
它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整. 通过七 个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯;计算机之间的传输媒介是光信号和电信号. 通过 "频率" 和 "强弱" 来表示 0 和 1 这样的信息. 要想传递各种不同的信 息, 就需要约定好双方的数据格式.但是就行通信的两台主机并不只是约定好协议就行,计算机生产厂商有很多, 计算机操作系统也有很多, 计算机网络硬件设备还是有很多,如何让这些不同厂商之间生产的计算机能够相互顺畅的通信?
2024-10-17 21:07:30
385
原创 线程及其应用
大部分情况,线程使用的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量归属单个 线程,其他线程无法获得这种变量。如果计算密集型 线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的 同步和调度开销,而可用的资源不变。线程是比进程更轻量化的一种执行流,是在进程内部执行的一种执行流。健壮性降低, 编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了 不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
2024-06-07 11:38:41
612
1
原创 linux信号
信号在内核中的表示:每个进程task_struct有一个指针指向一个表,表里有每个信号的编号、是否被阻塞(block表)、是否未决(pending表)和一个函数指针表示处理动作(自定义捕捉可修改)。内核态:一种操作系统的工作状态,可以让用户以操作系统的身份访问【3,4GB】,能够访问大部分的系统资源。=>本质上是用较件来模拟中断行为。用户态:一种受控的状态,只能访问自己进程地址空间的【0,3GB】,能够访问的资源是有限的。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
2024-04-13 14:57:01
354
原创 动静态库和文件系统
在进程的pcb中有一个struct file_struct 指针对象,对象中包含一个struct file类型的数组,其中该数组0为stdin(标准输入,键盘),1为stdout(标准输出,显示器),工为stderr(标准错误,显示器)会默认被打开。超级块:Super Block:存放文件系统本身的结构信息,如block和inode总量,未被使用的block和inode数,一个block和inode大小等。文件描述符的分配规则:在数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。
2024-04-05 19:06:44
1589
原创 linux进程控制
1.子进程在被父进程创建时会把页表中的数据( 虚拟地址、物理地址、访问权限字段、一个区域用于检查是否有内容和在磁盘是否分配有地址用来判断程序是否被挂起等)一起拷贝但是当子进程要修改内容时,则会另开一物理地址,并修改页表的映射关系使得我们看见虚拟地址没有被修改但内容变了。即当进程调用一种exe函数,该进程的用户空间代码和数据被完全替代,但调用exce 不创建新进程,且该进程id不变。若子进程没有退出,父进程必须在wait上进行阻塞等待, 直到子进程僵尸,wait回收。新进程为子进程,而原进程为父进程。
2024-03-15 15:03:11
793
原创 unorderd_map和unordered_set模拟实现
线性探测的缺陷是产生冲突的数据堆积在一块,这与其找下一个空位置有关系,因为找空位 置的方式就是挨着往后逐个去找,因此二次探测为了避免该问题,找下一个空位置的方法 为:hashi = ($H_0$ + i^2 )% m, 或者:hashi = ($H_0$ - i^2 )% m。开散列增容 : 桶的个数是一定的,随着元素的不断插入,每个桶中元素的个数不断增多,极端情况下,可 能会导致一个桶中链表节点非常多,会影响的哈希表的性能,因此在一定条件下需要对哈希表进行增容。哈希函数应该比较简单。
2024-02-15 18:34:43
1528
原创 C++特殊类
2.C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上 =delete,表示让编译器删除掉该默认成员函数。一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个 访问它的全局访问点,该实例被所有程序模块共享。将构造函数私有化,然后设计静态方法创建对象返回,后可使用operator new使全局的new调用拷贝构造禁止。1. 将类的构造函数私有,拷贝构造声明成私有。2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建。
2024-01-27 20:35:42
371
原创 C++11
node2的delete需要node1的next的delete,node1的next的delete需要node1的delete,node1的delete需要node2的prev的delete,node2的prev的delete需要node2的delete。定义时const修饰符后的左 值,不能给他赋值,但是可以取它的地址。右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引 用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能 取地址。
2024-01-26 19:11:26
1626
原创 位图和布隆过滤器
布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特 位一定为1。注意:布隆过滤器如果说某个元素不存在时,该元素一定不存在,如果该元素存在时,该元素可 能存在,因为有些哈希函数存在一定的误判。布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概 率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存 在”,它是用多个哈希函数,将一个数据映射到位图结构中。2. 排序 + 去重。
2024-01-15 21:12:31
353
原创 红黑树c++
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点。3. 如果一个节点是红色的,则它的两个孩子结点是黑色的。5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)。2. 检测其是否满足红黑树的性质。2. 根节点是黑色的。
2023-12-02 22:35:37
44
原创 AVL树实现
二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查 找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii 和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右 子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。
2023-11-28 22:27:56
50
原创 map和set
pair<iterator,bool> insert ( const value_type& x ) :在set中插入元素x,实际插入的是<x,x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在,返回<x在set中的位置,false>。const_iterator find ( const key_type& x ) const :在map中插入key为x的元素,找到返回该元 素的位置的const迭代器,否则返回cend。
2023-11-19 20:40:13
51
原创 搜索二叉树
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点 中,再来处理该结点的删除问题--替换法删除。情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除。情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除。若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。d. 要删除的结点有左、右孩子结点。b. 要删除的结点只有左孩子结点。
2023-11-09 18:00:40
68
1
原创 多态C++
2. 基类b对象和派生类d对象虚表是不一样的,这里我们发现Func1完成了重写,所以d的虚表 中存的是重写的Derive::Func1,所以虚函数的重写也叫作覆盖,覆盖就是指虚表中虚函数 的覆盖。5. 派生类的虚表生成:a.先将基类中的虚表内容拷贝一份到派生类虚表中 b.如果派生 类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数 c.派生类自己 新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。在类中,若含有虚函数,则类中隐含一个虚函数表指针,用来存放虚函数的地址。
2023-10-31 22:40:09
40
1
原创 继承C++
protected继承:基类的public成员->派生类的protected成员,基类的protected成员->派生类的protected成员,基类的private成员->在派生类中不可见。private继承:基类的public成员->派生类的private成员,基类的protected成员->派生类的private成员,基类的private成员->在派生类中不可见。继承是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。
2023-10-31 21:15:44
44
1
原创 prority_queue
3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特 定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元 素)。front():返回容器中第一个元素的引用;push_back():在容器尾部插入元素;size():返回容器中有效元素个数;1. 优先队列是一种容器适配器。
2023-10-02 22:38:20
180
1
原创 linux程序调试:gdb
list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数。info(或i) breakpoints:参看当前设置了哪些断点。delete breakpoints n:删除序号为n的断点。info(i) locals:查看当前栈帧局部变量的值。breaktrace(或bt):查看各级函数调用及参数。delete breakpoints:删除所有断点。disable breakpoints:禁用断点。
2023-10-02 21:53:15
70
1
原创 linux基础工具:vim
移动光标 vim可以直接用键盘上的光标来上下左右移动,但正规的vim是用小写英文字母「h」、「j」、「k」、 「l」,分别控制光标左、下、上、右移一格。「q」:按「q」就是退出,如果无法离开vim,可以在「q」后跟一个「!「/关键字」: 先按「/」键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直按 「n」会往后寻找到您要的关键字为止。「X」:大写的X,每按一次,删除光标所在位置的“前面”一个字符 「#X」:例如,「20X」表示删除光标所在位置的“前面”20个字符。
2023-10-02 17:59:38
64
1
原创 list模拟实现C++
因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代 器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。b.rbegin+rend:返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的 reverse_iterator,即begin位置。
2023-08-28 17:20:50
51
1
原创 vector模拟实现C++
vector是表示可变大小数组的序列容器,就像数组一样,vector也采用的连续存储空间来存储元素。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。a. begin+end:获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置 的iterator/const_iterator。b. cbegin+cend:获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的 reverse_iterator。
2023-08-25 18:41:14
54
1
原创 常用排序方法
是一种不稳定的排序。任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。前后指针法:将key设为最左边的数,prev指针指向开头,cur指针指向prev指针的后一个位置,cur找到比key小的值,找到后,prev++后交换prev和cur的值。挖坑法:设最左边的数为坑,右指针走,找比坑小的,然后交换,坑变为右指针的数,左指针走,依次轮回,直到相遇。
2023-08-20 18:38:27
82
1
原创 string
4.修改: push back(尾插),append(末尾追加字符串),+=重载(末尾追加字符串),c_str(返回c格式字符串),find+npos(从pos位置开始往后找字符c,返回该字符的位置),rfind(从pos位置开始往前找字符c,返回该字符的位置),substr(从字符串pos位置开始截取n个字符,然后返回)string是表示字符串的字符串类,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。3.访问遍历:[]重载,迭代器,范围for。
2023-08-08 22:10:11
24
原创 const成员与初始化列表
注意:const对象不能调用非const成员函数,非const对象可以调用const成员函数;const成员函数内不能调用其它非const成员函数,非const成员函数内可以调用其他的const成员函数。将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数 隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。3.每个成员变量在初始化列表中只能出现一次,且引用成员变量,const成员变量,自定义类型成员(无默认构造)必须在初始化列表初始化;
2023-08-08 18:53:46
40
原创 类和对象
类型为:类类型*const,在成员函数中不能给this指针赋值,且只能在成员函数中使用,当对象调用成员函数时,将对象的地址作为实参传递给this形参,所以对象不存储this指针,this指针存于栈帧中。在C++中,每个类的成员函数都有一个隐式的this指针,指向调用该成员函数的对象。2.在计算类的大小时,只需计算成员变量,不用计算成员函数,这是因为成员函数和成员变量分开存储,成员函数存储于公共代码区,计算方式与结构体类似。注意:若类只有成员函数或空类,则分配1个字节,不存储数据,只是占位,表示对象存在过。
2023-07-22 22:20:33
29
原创 c++入门
命名空间可以定义变量,函数,类型,分为全部展开和部分展开:using namespace+名(全部展开),using+名::变量/函数/类型(部分展开)。3.函数重载是指多个同名函数定义,这些函数的参数不同(类型不同,个数不同,顺序不同)。在编译器中,使用函数名修饰区别相同函数名的函数,较为复杂,不展开,并且不同的编译器的函数名修饰规则不同。提示std是c++标准库的命名空间,使用using namespace std时,可以直接使用cout 和cin,否则还需要写std::cin/cout。
2023-07-22 20:50:01
31
原创 自定义类型c语言
如:vs环境下默认对齐数是8,gcc环境无默认对齐数,则为成员自身大小);3.当成员全部存放进去后,结构体的总大小必须是所有成员的对齐数中最大对齐数的整数倍,如果不够,则浪费空间对齐;4.如果结构体里嵌套了结构体,嵌套的结构体对齐到自己成员最大对齐数的整数倍,结构体整体大小就是所有最大对齐数(包括嵌套结构体的对齐数)的整数倍。struct stu为自定义结构体类型,s1为结构体变量,初始化与其他类型的变量相同,访问结构体成员使用.(成员访问运算符),方式为结构体变量.结构体成员。
2023-04-11 22:24:02
36
原创 字符串函数和内存函数
两个函数都是在dest字符串后追加str字符串并返回dest的起始地址,但是strcat是将全部的str字符串追加,而strncat是将n个字节的str追加到dest后。两个函数是比较字符串是否相同,相同返回0,不相同时根据相同位置的字符的ASCLL,p1>p2返回大于0的数,p1<p2返回小于0的数。memcmp是可以用于任意类型的数据进行比较p1和p2指针开始的n个字节,相同返回0,不相同时根据相同位置的字符的ASCLL,p1>p2返回大于0的数,p1<p2返回小于0的数。
2023-03-19 14:44:22
185
原创 数据的储存
例:(float)5.5=>(二进制形式)1(1*2^2)0(0*2^1)1(1*2^0).1(1*2^-1)=>1.011*2^2(1.011=M,2^2=2^E,E为101.1=>1.011移动的位数)=>(在内存中的形式)0(符号位)10000001(若为float,为E+127的二进制形式;原码,反码,补码相同,都是这个数的二进制形式在加上n(与该类型的bit差)个0,第一位是符号位正为,负为1。在内存中存储的都是二进制数据,而整形的二进制表示形式有:原码,反码,补码,并且存储的都是补码。
2023-03-14 21:52:59
57
原创 c语言扫雷
细节讲解:1.创建二维数组时要设置得大一些,防止玩家在输入时出现越界。例如创建一个11*11的棋盘,只需要到9*9,单独留给外围一圈。2.创建二维数组的棋盘时,要创建两个,一个用于设置雷,另一个用于展示已经选定的坐标。因为如果只用一个棋盘的话,容易混乱。思路讲解:扫雷与三子棋准备十分相似,都需要先创建二维数组,初始化,打印棋盘,设置雷,找雷。
2023-02-02 23:18:54
89
原创 c语言三子棋
思路讲解:首先,由于代码过长,一般将代码分为几个文件,大致分为如下:test.c(测试游戏逻辑),game.c(函数的实现),game.h(函数的声明)。接下来,先大致理清思路:提供菜单进入游戏,创建和初始化棋盘,划分好格子,玩家下棋,判断输赢,电脑下棋,判断输赢。3.电脑要做到随机下棋要使用rand函数,通过时间戳来设计srand。2.判断输赢时要充分考虑好各种情况,例如:玩家赢,电脑赢,平局。注意事项:1.棋盘的初始化看作二维数组的初始化,先把每个空给上空格,便于输入。
2023-02-01 20:47:50
33
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人