- 博客(126)
- 收藏
- 关注
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 I/O多路复用
I/O 多路复用(I/O多路转接)使得程序能同时监听多个文件描述符,能够提高程序的性能,Linux下实现I/O多路复用的系统调用主要有 selectpoll和epoll。
2024-01-27 22:14:06
1083
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 TCP 三次握手 四次挥手以及滑动窗口
滑动窗口(Sliding window)是一种流量控制技术。早期的网络通信中,通信双方不会考虑网络的拥挤情况直接发送数据。由于大家不知道网络拥塞状况,同时发送数据,导致中间节点阻塞掉包谁也发不了数据,所以就有了滑动窗口机制来解决此问题。滑动窗口协议是用来改善吞吐量的一种技术,即容许发送方在接收任何应答之前传送附加的包。接收方告诉发送方在某一时刻能送多少包(称窗口尺寸)。TCP 中采用滑动窗口来进行传输控制,滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据。
2024-01-25 21:54:47
2480
1
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 cmake:编写一个简单的CMakeLists.txt文件
这个生成的app就是我们在 CMakeLists.txt文件中指定的可执行文件。查看电脑上安装cmake的版本 ,由此写入CMakeLists.txt文件。在同一文件夹下再创建一个文件夹用来存储makefile等一系列文件。得到cpp文件中的运行结果。然后进入该目录,执行指令。
2023-11-09 10:13:06
572
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 vscode配置环境变量
解压完成之后,找到这个文件的bin目录复制路径后,添加到环境变量中。然后选择Files这个选项。首先点击下面这个链接。向下移选择下载这个文件。
2023-11-06 14:41:09
545
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 创建基于多任务的并发服务器
在上述代码中,子进程需要关闭服务端套接字的原因是,服务端套接字已经在父进程中被创建并绑定到了指定的地址和端口,而子进程继承了父进程的所有资源,包括服务端套接字。有几个请求服务的客户端,我们就创建几个子进程。上述代码是基于多进程实现的并发回声服务器。这里父进程传递的套接字文件描述符,
2023-11-05 11:30:42
1307
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 关于栈内存的一些总结
因此,在考虑栈和堆的增长方向时,需要考虑所使用的架构(32位或64位)以及操作系统和编译器的设计。这意味着,对于一个多字节的数据,比如一个整数,它的最低字节会存储在较低的内存地址上,而最高字节会存储在较高的内存地址上。例如,在x86架构的小端序操作系统中,栈通常是从高地址向低地址增长的,而堆通常是从低地址向高地址增长的。因此,栈和堆的增长方向在小端序操作系统中不是唯一确定的,而是由特定的架构和操作系统的设计决定的。在小端序操作系统中,栈和堆的增长方向通常是与特定架构和操作系统相关的,因此不是唯一确定的。
2023-11-02 10:14:14
875
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 网络编程中关于UDP套接字的一些知识点
需要注意的是,编译时指定的本地IP地址和端口号只是用于绑定程序到指定的网络接口和端口,不会影响程序与其他主机之间的通信。然而,在编写UDP程序时,通常需要指定本地IP地址和端口号,以便程序能够绑定到正确的网络接口,并监听指定的端口。总之,保存结构体变量长度的变量地址作为sendto函数和recvfrom函数的最后一个参数,是为了确保函数能够正确地处理地址信息,以便进行数据的正确发送和接收。对于recvfrom函数,它接收的数据通常是通过参数中的缓冲区指针和指定的大小来保存的。
2023-11-01 15:14:51
663
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 博客摘录「 TCP/IP网络编程——习题答案」2023年10月30日
:通过`accept()`函数接受客户端的连接请求,创建一个新的套接字`clnt_sock`与客户端进行通信。在这里,`(char*)(&str_len)`是将整型变量`str_len`的地址强制转换为字符型指针。`:设置`clnt_addr_size`变量为`clnt_addr`结构体的大小,用于接收客户端的地址信息。强制类型转换`(char*)`的作用是将整型指针转换为字符型指针,这样可以将整型变量的地址作为字符型指针传递给`write()`函数,从而发送整型变量的内容。
2023-10-30 14:47:58
531
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 博客摘录「 TCP/IP网络编程——习题答案」2023年10月29日
2. 文件大小不是`BUF_SIZE`的整数倍:此时最后一次从文件中读取的数据块大小可能小于`BUF_SIZE`,因此需要使用`write(clnt_sd, buf, read_cnt)`将实际读取的数据块发送给客户端。1. 文件大小正好是`BUF_SIZE`的整数倍:此时每次从文件中读取`BUF_SIZE`字节的数据块,并使用`write(clnt_sd, buf, BUF_SIZE)`将数据块发送给客户端。`:将从文件中读取的数据块`buf`通过已连接的套接字`clnt_sd`发送给客户端。
2023-10-29 22:39:57
1218
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 linux中的read函数和write函数详解
read函数会从文件描述符中读取count个字节的数据,并将其存储到buf中。如果读取成功,read函数返回实际读取的字节数;write函数将buf中的count个字节的数据写入到文件描述符fd所指向的文件中。如果写入成功,write函数返回实际写入的字节数;因此,read函数每次读取的是指定字节数的数据,而不是一个字符。如果需要逐个读取字符,可以使用循环结构,每次读取一个字节的数据,直到读取完整个字符串。如果要逐个写入字符,可以使用循环结构,每次写入一个字节的数据,直到写入完整个字符串。
2023-10-29 13:17:38
1135
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 最长上升子序列(二分)代码模板
用二分的思想求最长上升子序列的思想就是保持单调性,用一个q[]数组来作为一个单调数组。每次将a[i]放进q数组中,但是要保持单调性,
2023-10-22 22:53:26
1989
1
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 字符串哈希代码模板
任意字符不可以映射成0,否则会出现不同的字符串都映射成0的情况,比如A,AA,AAA皆为0。可以将h[]中的每一个字符串看做一个p进制数,上图=后就是将他转化为10进制数。移动完之后就可以得到l到r区间的映射的哈希值了。P = 131或者1331,Q取2的64次方。就能保证99.99%不会出现冲突。字符串哈希就是假设不出现冲突,当。上述代码就是核心代码。
2023-10-19 23:40:52
595
![](https://csdnimg.cn/release/blogv2/dist/pc/img/listFixedTop.png)
原创 并查集代码模板
并查集就是一个集合。这里需要用一个p[]数组来存储他的父节点,例如p[1] = 2,意思为1节点的父节点为2节点。这样就可以连接成一个集合。查找函数是并查集的核心,因为这里还加了一个路径压缩,第一次查找完后,就直接将他的父节点赋值为他所在集合的祖宗节点了。合并集合只需要将一个集合的祖宗节点连接到另一个集合的祖宗节点的下面。还有p[]数组一开始要初始化为自己,因为一开始所有节点都是祖宗节点。这里我画张图来演示。
2023-10-19 10:23:43
187
原创 项目服务器登录部分
若无错误,先需要清空接收头部节点,保证接受头部节点中没有之前的数据,然后将接收的数据复制到接收头部节点中。和接收消息内容节点创建逻辑节点,加入到逻辑队列中。第一个参数是起始地址(可以看作已经读取的字节长度),第二个是总长度,第三个是回调函数。和消息长度,每次从头部节点取出数据前需要将网络字节序转化为本地字节序。若获取消息id和消息长度无错误,则创建接收消息内容节点然后调用。该函数指定读取长度大小,传入需要读取的长度和执行的回调。中的内容,这是已经将发生过来的数据完整的读取下来了。
2024-08-19 20:15:51
547
原创 客户端登录逻辑
使用槽函数来发送数据主要是为了保证数据的有序,而且槽函数保证线程安全。读取完的数据会从缓冲区中移除,然后将获取的消息id和消息长度以及消息内容传入处理数据。中的构造函数中连接,当成功与聊天服务器建立连接后发出。消息格式,使用数据流发送数据,是为了保证数据的准确性。服务器发送数据时,就需要将数据设置为大端序。先将获取的数据加入缓冲区,通过数据流读取数据,变量判断是否接收完全,可以保证数据有序。将网关服务器发送的数据通过信号传递给。对应的槽函数,调用套接字中的。信号,意味着可以发送消息。
2024-08-18 16:34:53
265
原创 Qt实现自定义控件
在外部调用接口,将设置的动态属性名称传进去,这样自定义控件的实现就完成了。还要自定义一个类,这里先列举自定义按钮的实现方式。首先实现自定义控件必然需要。(通过类提升),名称为。下面是设置的是类型为。
2024-08-18 16:19:09
315
原创 一些关于网络的笔记
局域网(LAN,Local Area Network)是指在较小的地理范围内,通常是在单个建筑物、办公室、校园或者企业内部建立的一个网络。这种网络连接了位于同一地区的多台计算机和其他网络设备,使它们能够相互通信和共享资源,如文件、打印机、互联网连接等。局域网通常由局域网交换机或者集线器等网络设备连接起来,通过以太网、Wi-Fi等局域网技术进行通信。它们提供了高速、低成本的数据传输,使得组织内的各种信息资源可以迅速地共享和利用。局域网的范围通常比较小,覆盖的地理区域通常不超过几百米到几千米。
2024-03-27 19:22:46
1255
原创 树状数组的三种代码模板
下标从一开始。所有奇数等于本身,偶数/2等于所在层数。二进制末尾有几个0就在第几层。每一个树状数组中表示的都是这么一个区间的和,左开右闭。写成lowbit(x),返回的就是2^k,k就是末尾有几个0。这是求和代码单点修改。
2024-03-27 19:22:03
367
原创 C++中的内存分区
全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量和静态变量又分为初始化的和未初始化的,在C++里面没有这个区分了,它们共同占用同一块内存区,在该区定义的变量若没有初始化,则会被自动初始化,例如int型变量自动初始为0。堆:就是那些由 new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个 delete。自由存储区:如果说堆是操作系统维护的一块内存,那么自由存储区就是C++中通过new和delete动态分配和释放对象的抽象概念。
2024-03-26 19:54:02
419
原创 不使用额外空间交换两个数
总的来说,加法方法适用于几乎所有的数值类型,而异或方法适用于整数类型和字符类型。在实际应用中,可以根据具体的需求和数据类型来选择适合的方法进行交换。加法和异或这两种方法都是用于交换两个数的值而不使用额外空间的方法。
2024-03-26 19:53:23
498
原创 构造函数、析构函数、虚函数可否声明为内联函数
在使用指针或引用调用虚函数时,如果对象的类型在运行时才能确定,编译器就无法在编译期确定调用的函数,而需要等到运行时根据对象的实际类型来确定。你提出了一个很重要的观点,是的,不是所有的虚函数都是在运行时确定的。在使用指针或引用调用虚函数时,编译器无法在编译期确定调用的函数,是因为编译器只能根据指针或引用的静态类型来确定调用的函数,而无法确定其指向的对象的实际类型。创建对象时,对象的类型是在运行时确定的,因此编译器无法在编译期确定对象的实际类型,这也是为什么无法在编译期确定虚函数的调用目标的原因之一。
2024-03-24 09:47:55
438
原创 为什么析构函数一般写成虚函数?
由于类的多态性,基类指针可以指向派生类的对象,如果删除该基类的指针,就会调用该指针指向的派生类析构函数,而派生类的析构函数又自动调用基类的析构函数,这样整个派生类的对象完全被释放。如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全,造成内存泄漏。所以将析构函数声明为虚函数是十分必要的。在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生,要将基类的析构函数声明为虚函数。
2024-03-24 09:47:12
319
原创 什么是虚拟继承
虚拟继承的作用是在多重继承的情况下,保证间接基类的实例只会在派生类对象中存在一次,而不会重复出现。多重继承本身就容易引起设计上的混乱和错误,所以在实际开发中应该尽量避免使用多重继承,或者使用单一继承和组合的方式来代替多重继承。虚拟继承的原理是通过虚基指针和虚基表来实现的,每个包含虚拟基类的类都有一个虚基指针,指向一个虚基表,虚基表中存放了虚拟基类的偏移量,用于定位虚拟基类的位置⁴。菱形继承是指一个派生类继承了两个或多个直接基类,而这些直接基类又继承自同一个间接基类,形成了一个菱形的继承结构²。
2024-03-23 10:06:43
411
原创 什么是TCP粘包/拆包?发生的原因?
一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和粘包问题。1、应用程序写入数据的字节大小大于套接字发送缓冲区的大小.2、进行MSS大小的TCP分段。( MSS=TCP报文段长度-TCP首部长度)3、以太网的payload大于MTU进行IP分片。( MTU指:一种通信协议的某一层上面所能通过的最大数据包大小。1、消息定长。2、在包尾部增加回车或者空格符等特殊字符进行分割3、将消息分为消息头和消息尾。
2024-03-23 10:03:48
990
原创 线程池的知识
线程池中的线程数量最直接的限制因素是中央处理器(CPU)的处理器(processors/cores)的数量N :如果你的CPU是4-cores的,对于CPU密集型的任务(如视频剪辑等消耗CPU计算资源的任务)来说,那线程池中的线程数量最好也设置为4(或者+1防止其他因素造成的线程阻塞);,因为线程间竞争的不是CPU的计算资源而是IO,IO的处理一般较慢,多于cores数的线程将为CPU争取更多的任务,不至在线程处理IO的过程造成CPU空闲导致资源浪费。这将唤醒正在等待任务的子线程,不过。
2024-01-31 19:44:16
290
原创 两种高效的事件处理模式
服务器程序通常需要处理三类事件:I/O 事件、信号及定时事件。和同步 I/O模型通常用于实现模式,异步 I/O模型通常用于实现模式。为了避免频繁的无效写操作和优化服务器性能,通常会将写就绪事件的注册放在读就绪事件之后。这样可以确保在真正需要写入数据时才进行相应的操作,而不是每次都等待写就绪事件。要求主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程(逻辑单元),将socket 可读可写事件放入请求队列,交给工作线(子线程)程处理。
2024-01-31 11:20:59
637
原创 HTTP协议(应用层的协议)
HTTP 是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通过使用网页浏览器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80我们称这个客户端为用户代理程序(user agent)。应答的服务器上存储着一些资源,比如 HTML 文件和图像。我们称这个应答服务器为源服务器(origin server)。在用户代理和源服务器中间可能存在多个“中间层”,比如代理服务器、网关或者隧道(tunnel)。
2024-01-31 09:49:36
1519
原创 Unix/Linux上的五种IO模型
调用者调用了某个函数,等待这个函数返回,期间什么也不做,不停的去检查这个函数有没有返回,必须等这个函数返回才能进行下一步动作。阻塞并不是函数的行为,而是跟文件描述符有关。通过设置文件描述符来控制是阻塞还是非阻塞。
2024-01-30 19:53:35
558
原创 阻塞和非阻塞、同步和异步(网络IO)
异步是操作系统将数据放到buf中的,同步是TCP接收缓冲区放入buf中的。通过异步IO接口将sockfd,buf,通知方式传给操作系统,并没有像同步一样从内核缓冲区中读取数据。一个典型的网络IO接口调用,分为两个阶段,分别是“数据就绪” 和 “数据读写”,数据就绪阶段分为。同步表示A向B请求调用一个网络IO接口时(或者调用某个业务逻辑API接口时),数据的读写都是。来通知异步 I/O 操作完成,而在事件驱动的异步 I/O 模型中,通常会使用。阻塞和非阻塞,表现得结果就是,阻塞和非阻塞都是同步 IO。
2024-01-30 11:16:19
362
原创 UDP通信以及本地套接字
本地套接字的作用:本地的进程间通信有关系的进程间的通信没有关系的进程间的通信本地套接字实现流程和网络套接字类似,一般采用TCP的通信流程。// 本地套接字通信的流程 - tcp// 服务器端1. 创建监听的套接字2. 监听的套接字绑定本地的套接字文件 -> server端// 绑定成功之后,指定的sun_path中的套接字文件会自动生成。3. 监听4. 等待并接受连接请求5. 通信接收数据:read/recv发送数据:write/send6. 关闭连接。
2024-01-29 21:45:17
1033
原创 TCP通信流程以及套接字函数
UDP(用户数据报协议)被认为是不可靠的主要是因为它缺乏一些保证数据可靠性的机制,这使得在传输过程中可能出现数据丢失、乱序或重复的情况。无连接性: UDP是一种无连接的协议,不需要在通信的两端建立和维护连接。这虽然提高了传输效率,但也意味着在传输过程中不进行状态检查和确认。不提供流控制: UDP不提供流控制机制,因此发送方会以最大速率发送数据,而不考虑接收方的处理能力。这可能导致数据包丢失或过载。不提供重传机制: 在UDP中,如果一个数据包在传输过程中丢失,协议本身不提供重传机制。这意味着。
2024-01-25 14:35:26
897
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人