Linux
未读1. IO多路转接(复用)IO多路转接也称为IO多路复用,它是一种网络通信的手段(机制),通过这种方式可以同时监测多个文件描述符并且这个过程是阻塞的,一旦检测到有文件描述符就绪( 可以读数据或者可以写数据)程序的阻塞就会被解除,之后就可以基于这些(一个或多个)就绪的文件描述符进行通信了。通过这种方式在单线程/进程的场景下也可以在服务器端实现并发。常见的IO多路转接方式有:select、poll、epoll。
下面先对多线程/多进程并发和IO多路转接的并发处理流程进行对比(服务器端):
多线程/多进程并发
主线程/父进程:调用 accept()监测客户端连接请求
如果没有新的客户端的连接请求,当前线程/进程会阻塞
如果有新的客户端连接请求解除阻塞,建立连接
子线程/子进程:和建立连接的客户端通信
调用 read() / recv() 接收客户端发送的通信数据,如果没有通信数据,当前线程/进程会阻塞,数据到达之后阻塞自动解除
调用 write() / send() 给客户端发送数据,如果写缓冲区已满,当前线程 ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
在C++11中添加了定义原始字符串的字面量,定义方式为:R “xxx(原始字符串)xxx”其中()两边的字符串可以省略。原始字面量R可以直接表示字符串的实际含义,而不需要额外对字符串做转义或连接等操作。
比如:编程过程中,使用的字符串中常带有一些特殊字符,对于这些字符往往要做专门的处理,使用了原始字面量就可以轻松的解决这个问题了,比如打印路径:
1234567891011121314#include<iostream>#include<string>using namespace std;int main(){ string str = "D:\hello\world\test.text"; cout << str << endl; string str1 = "D:\\hello\\world\\test.text"; cout < ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. finalC++中增加了final关键字来限制某个类不能被继承,或者某个虚函数不能被重写,和Java的final关键字的功能是类似的。如果使用final修饰函数,只能修饰虚函数,并且要把final关键字放到类或者函数的后面。
1.1 修饰函数如果使用final修饰函数,只能修饰虚函数,这样就能阻止子类重写父类的这个函数了:
123456789101112131415161718192021222324252627class Base{public: virtual void test() { cout << "Base class..."; }};class Child : public Base{public: void test() final { cout << "Child c ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. 委托构造函数委托构造函数允许使用同一个类中的一个构造函数调用其它的构造函数,从而简化相关变量的初始化。下面举例说明:
12345678910111213141516171819202122232425262728293031323334353637#include <iostream>using namespace std;class Test{public: Test() {}; Test(int max) { this->m_max = max > 0 ? max : 100; } Test(int max, int min) { this->m_max = max > 0 ? max : 100; // 冗余代码 this->m_min = mi ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。
C++11 中提供了三种智能指针,使用这些智能指针时需要引用头文件 :
std::shared_ptr:共享的智能指针std::unique_ptr:独占的智能指针std::weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视 shared_ptr 的。
1. 基本使用方法弱引用智能指针std::weak_ptr可以看做是shared_ptr的助手,它不管理shared_ptr内部的指针。std::weak_ptr没有重载操作符*和-&g ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
在C++程序开发中,为了提高程序的健壮性,一般会在定义指针的同时完成初始化操作,或者在指针的指向尚未明确的情况下,都会给指针初始化为NULL,避免产生野指针(没有明确指向的指针,操作也这种指针极可能导致程序发生异常)。C++98/03 标准中,将一个指针初始化为空指针的方式有 2 种:
12char *ptr = 0;char *ptr = NULL;
在底层源码中NULL这个宏是这样定义的:
1234567#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif#endif
也就是说如果源码是C++程序NULL就是0,如果是C程序NULL表示(void*)0。那么为什么要这样做呢? 是由于 C++ 中,void * 类型无法隐式转换为其他类型的指针,此时使用 0 代替 ((void *)0 ...
配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:
关注公众号:爱编程的大丙,或者进入大丙课堂学习。
1. constexpr1.1 const在C++11之前只有const关键字,从功能上来说这个关键字有双重语义:变量只读,修饰常量,举一个简单的例子:
12345678910111213void func(const int num){ const int count = 24; int array[num]; // error,num是一个只读变量,不是常量 int array1[count]; // ok,count是一个常量 int a1 = 520; int a2 = 250; const int& b = a1; b = a2; // error a1 = 1314; cout << "b: " << b << endl; // ...
1. 单线程/进程在TCP通信过程中,服务器端启动之后可以同时和多个客户端建立连接,并进行网络通信,但是在介绍TCP通信流程的时候,提供的服务器代码却不能完成这样的需求,先简单的看一下之前的服务器代码的处理思路,再来分析代码中的弊端:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152// server.c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <arpa/inet.h>int main(){ // 1. 创建监听的套接字 int lfd = socket(AF_INET, SOCK_STREAM, 0); // 2. 将socket()返回值和本地的IP端口绑定到一起 struct sockaddr_in addr; ...
1. TCP状态转换在TCP进行三次握手,或者四次挥手的过程中,通信的服务器和客户端内部会发送状态上的变化,发生的状态变化在程序中是看不到的,这个状态的变化也不需要程序猿去维护,但是在某些情况下进行程序的调试会去查看相关的状态信息,先来看三次握手过程中的状态转换。
1.1 三次握手123在第一次握手之前,服务器端必须先启动,并且已经开始了监听 - 服务器端先调用了 listen() 函数, 开始监听 - 服务器启动监听前后的状态变化: 没有状态 ---> LISTEN
当服务器监听启动之后,由客户端发起的三次握手过程中状态转换如下:
第一次握手:
客户端:调用了connect() 函数,状态变化:没有状态 -> SYN_SENT
服务器:收到连接请求SYN,状态变化:LISTEN -> SYN_RCVD
第二次握手:
服务器:给客户端回复ACK,并且请求和客户端建立连接,状态无变化,依然是 SYN_RCVD
客户端:接收数据,收到了ACK,状态变化:SYN_SENT -> ESTABLISHED
第三次握手:
客户端:给服务器回复A ...
TCP协议是一个安全的、面向连接的、流式传输协议,所谓的面向连接就是三次握手,对于程序猿来说只需要在客户端调用connect()函数,三次握手就自动进行了。先通过下图看一下TCP协议的格式,然后再介绍三次握手的具体流程。
1. tcp协议介绍
在Tcp协议中,比较重要的字段有:
源端口:表示发送端端口号,字段长 16 位,2个字节
目的端口:表示接收端端口号,字段长 16 位,2个字节
序号(sequence number):字段长 32 位,占4个字节,序号的范围为 [0,4284967296]。
由于TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号
首部中的序号字段则是指本报文段所发送的数据的第一个字节的序号,这是随机生成的。
序号是循环使用的,当序号增加到最大值时,下一个序号就又回到了0
确认序号(acknowledgement number):占32位(4字节),表示收到的下一个报文段的第一个数据字节的序号,如果确认序号为N,序号为S,则表明到序号N-S为止的所有数据字节都已经被正确地接收到了。
8个标志位(Flag):
CWR: ...