面经啊啊啊啊啊啊

面经

C++

对面向对象的理解。

在这里插入图片描述

面向对象的三大特性

在这里插入图片描述

讲一下多态

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

C++内存分布

在这里插入图片描述

C语言实现封装

利用C语言的头文件,在头文件中对类对象进行前置声明,在将实现方法进行一个声明,再在.c文件中进行一个实现,使得用户只能通过接口调用该对象。

C语言实现继承

子类对象中声明一个父类对象就可以了

C语言实现多态

函数指针+继承

内存泄露

什么是内存泄露
概念:本该被回收的对象,因为别的原因却没有被回收掉的情况
比如 new 未delete情况
内存泄露的问题:
内存泄露会导致系统卡顿–给用户带来的体验不好
内存占用过高,有可能导致程序崩溃

导致内存泄露原因:
1.变量不合理作用域 本该放在局部的变量放在了全局
2. 静态集合类 长生命周期的对象持有短生命周期对象的引用。
3. 各种连接,如数据库连接、网络连接和IO连接
4.内存开辟未释放情况

inline关键字的缺点与优点

在这里插入图片描述

volatile关键字作用(腾讯一面)

1)volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,告诉编译器对该变量不做优化,都会直接从变量内存地址中读取数据,从而可以提供对特殊地址的稳定访问。。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
2)在单任务环境中,如果在两次读取变量之间不改变变量的值,编译器就会发生优化,会将RAM中的值赋值到寄存器中;由于访问寄存器的效率要高于RAM,所以在需要读取变量时,直接寄存器中获取变量的值,而不是从RAM中。

3)在多任务环境中,虽然在两次读取变量之间不改变变量的值,在一些情况下变量的值还是会发生改变,比如在发生中断程序或者有其他的线程。这时候如果编译器优化,依旧从寄存器中获取变量的值,修改的值就得不到及时的响应(在RAM还未将新的值赋值给寄存器,就已经获取到寄存器的值)。

4)要想防止编译器优化,就需要在声明变量时加volatile关键字,加关键字后,就在RAM中读取变量的值,而不是直接在寄存器中取值。简单概括来讲:编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值

指针与引用区别

在这里插入图片描述

为什么结构体要内存对齐

**不同硬件平台对存储空间的处理上存在很大的不同。**某些平台对特定类型的数据只能从特定地址开始存取,而不允许其在内存中任意存放。例如Motorola 68000 处理器不允许16位的字存放在奇地址,否则会触发异常,因此在这种架构下编程必须保证字节对齐。

但最常见的情况是,如果不按照平台要求对数据存放进行对齐,会带来存取效率上的损失。比如32位的Intel处理器通过总线访问(包括读和写)内存数据。每个总线周期从偶地址开始访问32位内存数据,内存数据以字节为单位存放。如果一个32位的数据没有存放在4字节整除的内存地址处,那么处理器就需要2个总线周期对其进行访问,显然访问效率下降很多。

全局变量、静态变量、 局部变量区别?

区别全局变量局部变量静态变量
存储位置数据段栈区数据段
连接属性具有外部连接性,可以在工程的其他文件中使用不可以,函数调用完生命周期结束不具有外部连接性,只可以在本文件中使用
生命周期跟随程序跟随调用函数跟随程序

extern关键字作用

struct和类的区别?

  1. 关于默认访问权限:class中默认的成员访问权限是private的,而struct中则是public的。
  2. 关于继承方式:class继承默认是private继承,而struct继承默认是public继承

宏定义与常量定义的区别?

① 两者在代码生成时所被处理的阶段不同,宏的替换在预编译(预处理)阶段,而const 常量则在编译阶段才确定,并分配内存
②const常量有数据类型,而宏没有数据类型。编译器只对宏在预编译阶段进行替换,却没有类型及安全检查,所以在替换过程中可能会出现错误,但是编译器却可以对const所定义的常量进行类型和安全检查,由宏引起的错误一般调试不出来,而const常量可以。

描述一下一个类对象的内存结构

看这里

C++11

C程序的存储区有哪些?

在这里插入图片描述
栈区(stack):由编译器自动分配与释放,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。其操作类似于数据结构中的栈。
堆区(heap):一般由程序员自动分配,如果程序员没有释放,程序结束时可能有OS回收。其分配类似于链表。
数据段:存放的是全局数据、与静态数据,全局数据又可分为已初始化的全局区(data)和未初始化的全局区(BSS);
代码段:可执行代码和只读常量(文字常量区);
内存映射段:文件映射、动态库、匿名映射

解释一下抽象类

在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。
调用的话:基类的指针与引用去调用派生类的方法。

智能指针如何实现?

RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。
在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象.

智能指针的原理

在这里插入图片描述

各个版本的智能指针及其特性

C++ 98 auto_ptr : 解决浅拷贝
1.转移资源 2.转移释放权限
C++11 中
unique_ptr() :这个智能指针的作用就是防拷贝,既然拷贝可能会带来资源重复释放,资源泄露的问题,那我从根源上就不让你拷贝。
shared_ptr
在这里插入图片描述
shared_ptr中的循环引用问题
在这里插入图片描述

用C++实现一个不能被继承的类

将构造函数和析构函数声明为私有函数,该函数就不可被继承。同时为了该类可以被实例化,在类中定义一个静态函数,返回初始化的一个类对象。

右值引用

左值: 就是有确定的内存地址、有名字的变量,可以被赋值,可以在多条语句中使用;
右值: 1、字符常量都是右值 2、表达式中间的运行结果为右值
3.函数以值返回的方式也都是右值。
C语言中的纯右值,比如:a+b, 100将亡值。比如:表达式的中间结果、函数按照值的方式进行返回。
普通引用只能引用左值,不能引用右值,const引用既可引用左值,也可引用右值。
左值引用与右值引用区别
左值引用:
相当于给一个变量取别名操作。对别名数据操作相当于对原始数据操作
右值引用:
目的:提高效率。提出类移动构造以及移动赋值。

解释一下栈和堆的区别?

栈:栈是一种线性的数据结构,读取规则是先进后出。栈中的数据占用的内存空间的大小是确定的,便于代码执行时的入栈、出栈操作,并由系统自动分配和自动释放内存可以及时得到回收,相对于堆来说,更加容易管理内存空间。

堆:堆是一种树形数据结构,读取相对复杂。堆是动态分配内存,内存大小不一,也不会自动释放。栈中的数据长度不定,且占空间比较大。便于开辟内存空间,更加方便存储。

(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小,进程栈的大小64bits的Windows默认1M,64bits的Linux默认10M;
(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需我们手工实现。
(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。
(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内存(eip),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(ebp),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是调用函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。

从以上可以看到,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低。栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。虽然栈有众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,主要还是用堆。

无论是堆还是栈,在内存使用时都要防止非法越界,越界导致的非法内存访问可能会摧毁程序的堆、栈数据,轻则导致程序运行处于不确定状态,获取不到预期结果,重则导致程序异常崩溃,这些都是我们编程时与内存打交道时应该注意的问题。

sort底层说一下(腾讯一面)

毫无疑问是用到了快速排序,但不仅仅只用了快速排序,还结合了插入排序和堆排序。
看这里

vector底层为何2倍扩容?(腾讯一面)

C++异常(腾讯一面)

异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误
try区段:这个区段中包含了可能发生异常的代码,在发生了异常之后,需要通过throw抛出。
throw子句:throw 子句用于抛出异常,被抛出的异常可以是C++的内置类型(例如: throw int(1);),也可以是自定义类型。
catch子句:每个catch子句都代表着一种异常的处理。catch子句用于处理特定类型的异常。

C++虚函数机制如何实现?

编译器为每个含有虚函数的类建立一个虚函数表,表中存放了该类的虚函数的入口地址,实例化带虚函数的类的对象时,编译器在对象中附加一个vpointer指针,该指针指向该类的虚函数表;不论类中有多少个虚函数,但仅给类的对象附加一个虚指针。(一般虚指针放在对象的开头位置)类中的虚函数入口地址通过vpointer加上一个偏移地址来获得

malloc/free & new/delete的区别是什么?

  1. 编译时,New可以根据对象的类型,自动决定对象的大小;而malloc需要显式指定需要分配空间的大小。
  2. New返回指向正确类型的指针,不必进行强制类型转换;而malloc返回void *,必须进行强制类型转换,可能带来错误。
  3. 用new生成对象时,会调用构造函数, 用malloc则不会;同样,用delete删除对象时,会调用析构函数, 用free则不会.
  4. 如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。因此,new/delete必须配对使用,malloc/free也一样.

友元函数与友元类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

单继承、多继承、虚拟继承区别

在这里插入图片描述
在这里插入图片描述
虚拟继承:主要是为了解决菱形继承的问题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

hash冲突的解决

这里

public、protected、private区别

修饰成员函数或成员变量时:
protected、private均不可在类外被访问。
public:可被访问。
在这里插入图片描述

STL中迭代器失效

vector:
在这里插入图片描述
3.swap函数会造成迭代器失效。
string:
1.在这里插入图片描述
在这里插入图片描述

什么是STL?

在这里插入图片描述

STL六大组件

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

static关键字

1、修饰函数的局部变量:
特点:有默认值0,只执行一次,运行一开始就开辟了内存,内存放在全局
2、修饰全局函数和全局变量:
特点:只能在本源文件使用
3、修饰类里面的成员变量:
特点:和1差不多,定义多个static y,但只有一个y,不进入类的大小计算,不依赖于类对象的存在而存在(可直接调用,要进行外置声明)
4、修饰类的成员函数:
特点:f():括号里无this指针,只能调用他的本类静态函数和他的静态变量,即是用static修饰过的不依赖于类对象的存在而存在(可不进行外置声明,直接调用)

在这里插入图片描述
static函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static修饰的函数),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件.
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。
在这里插入图片描述

在这里插入图片描述
静态成员函数
在这里插入图片描述
2.静态成员函数的访问方式与静态成员的访问方式相同
3.普通成员函数可访问静态成员变量、也可以访问非静态成员变量
4.静态成员函数也会受到权限的约束

const关键字

https://blog.csdn.net/qq_45313714/article/details/117979894

extern"C"

在这里插入图片描述
在这里插入图片描述

C++内存分布

在这里插入图片描述

栈区(stack):由编译器自动分配与释放,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。其操作类似于数据结构中的栈。
堆区(heap):一般由程序员自动分配,如果程序员没有释放,程序结束时可能有OS回收。其分配类似于链表。
数据段:存放的是全局数据、与静态数据,全局数据又可分为已初始化的全局区(data)和未初始化的全局区(BSS);
代码段:可执行代码和只读常量(文字常量区);
内存映射段:文件映射、动态库、匿名映射

struct 和class区别

struct能包含成员函数吗? 能!
struct能继承吗? 能!!
struct能实现多态吗? 能!!!
区别1:
1.结构体成员默认属性与类的默认属性不同,结构体默认为公有,而类默认为私有。
2.类的默认继承方式为私有,而结构体的继承方式为公有。
3.struct不支持模板,而class支持模板

vector与list区别

在这里插入图片描述

B/B+区别

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

智能指针

这里

操作系统

进程间通信

看这里

进程、线程、协程概念?区别?

这里

多进程与多线程对比

看这里

同步、异步、阻塞、非阻塞分别的含义?

同步:
异步:
看这里
在这里插入图片描述

阻塞:​ 调用IO方法的线程进入阻塞状态数据没到的话,线程阻塞,直到有数据来了唤醒
阻塞,就是这个时间段内的IO一直等待,应用程序不能做其他的事情
非阻塞:**做一件事如果是否成功没有马上得到反馈,就先放着。如果以后要知道是否真正成功了,那就自己得去询问。**比如你去汇款,现在说我要去汇款了,然后柜员说汇了,至于钱什么时候能到,那就要自己去问了,反正现在是得不到结果的。比如read(),现在设置为非阻塞之后呢,如果现在没有内容去读取,那么就返回说没有读到,至于数据什么时候来呢,你要去自己询问。所以配合非阻塞呢,一般是轮询。但是这样有个缺点,浪费了大量的CPU时间。

孤儿进程、僵尸进程概念及危害

项目孤儿进程僵尸进程
概念父进程先退出,子进程就称之为“孤儿进程”1.僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使没有读取到子进程退出的返回代码时就会产生僵死(尸)进程2.僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。3.所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
状态标识 (父进程)S睡眠状态Z僵尸状态
产生原因父进程先执行完,子进程还未退出父进程创建一个子进程,子进程相对于父进程来说提前退出。子进程在退出的时候会向父进程发送一个信号(SIGCHLD),而父进程对于该信号是忽略处理的,导致子进程在退出时,没有进程来回收子进程的资源(PCB),子进程就变为了僵尸进程。
解决思路没什么危害。因为该进程只是父进程换成了init,依然可以正常运行。1.重启操作系统(众所周知,重启可以解决计算机90%的问题)–不推荐2.干掉父进程,这样进程成功由僵尸进程转化为孤儿进程,它就会被1号进程所领养,最后回收资源。(重点)3.进程等待。

僵尸进程危害?

1.进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态
2.维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说, Z状态一直不退出, PCB一直都要维护
3.那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!便会造成内存泄漏.

http get与post区别

在这里插入图片描述

死锁

锁的本质:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
乐观锁、悲观锁

静态链接与动态链接的区别

静态链接的过程就已经把要链接的内容已经链接到了生成的可执行文件中,就算你在去把静态库删除也不会影响可执行程序的执行;
而动态链接这个过程却没有把内容链接进去,而是在执行的过程中,再去找要链接的内容,生成的可执行文件中并没有要链接的内容,所以当你删除动态库时,可执行程序就不能运行。
各自优缺点:
看这里

进程间通信的方式,各自有什么特点?

1,匿名管道
2. 命名管道
3. 消息队列
4. 共享内存
5. 信号量
6. 套接字
7. 信号
共享内存
管道
信号
套接字

共享内存可以在不同的进程间通信吗?socket是怎么样进行进程间通信的?

看上面

Linux的虚拟内存(进程虚拟地址空间)了解吗?

地址空间

8、Linux多线程,同步怎么实现的?怎么保证线程安全?为什么要同步?

在这里插入图片描述
对临界资源采取加锁机制。POSIX信号量保证
添加链接描述

线程池

同上

内核态中的系统调用如果有多个线程同时调用,会阻塞吗?会发生什么?

不一定,若是对一块空间进行读操作的话,则不会阻塞。

内核态用用户态区别

当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。

多线程间的独有与共享

线程共享进程数据,但是也拥有自己一部分数据

独有:栈 , 寄存器(上下文信息),调度优先级,信号屏蔽字,标识符

共享:虚拟地址空间(代码段、数据段),文件描述符,信号处理方式,工作路径,用户组ID/组ID

死锁的产生

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

避免/解决死锁

死锁的避免

1.有序分配资源方法
2.银行家算法
3.及时释放不使用的资源。
4.资源一次性分配(给那些已经具备执行条件的先分配)

解决死锁

(1)最简单,最常用的方法就是进行系统的重新启动,不过这种方法代价很大,它意味着在这之前所有的进程已经完成的计算工作都将付之东流,包括参与死锁的那些进程,以及未参与死锁的进程。

(2)撤消进程,剥夺资源。终止参与死锁的进程,收回它们占有的资源,从而解除死锁。这时又分两种情况:一次性撤消参与死锁的全部进程,剥夺全部资源;或者逐步撤消参与死锁的进程,逐步收回死锁进程占有的资源。一般来说,选择逐步撤消的进程时要按照一定的原则进行,目的是撤消那些代价最小的进程,比如按进程的优先级确定进程的代价;考虑进程运行时的代价和与此进程相关的外部作业的代价等因素。

mutex和lock()区别

系统调用的概念

应用程序通过系统调用请求操作系统的服务。系统中的各种共享资源都
必须由操作系统统一掌管,因此在用户程序中,凡是与资源相关的操作
如(存储分配,I/O操作、文件管理等),都必须通过系统调用的方式拉完成
为什么有系统调用?
应用程序不能直接申请系统资源,必须通过系统调用的方式向操作系统
提出服务请求,由操作系统代为完成。这样保证了系统的稳定性和安全性。
系统调用分为 设备管理,文件管理,进程控制,进程通信,内存管理
系统调用与库函数区别:
1.库函数可能是封装好的系统调用,也可能不涉及系统调用。应用程序
可能发出系统调用,库函数也可能发出系统调用。
系统调用的原理:
第一,系统调用通过中断实现,需要完成栈切换。
第二,使用寄存器传参,这需要额外的保存和恢复的过程。

操作系统内存管理

操作系统内存管理:
总的来说,内存管理分为物理内存和虚拟内存管理
物理内存管理:
包括程序装入等概念、交换技术、连续分配管理方式和非连续分配管理方式
(分页、分段、段页式)
虚拟内存管理:
包括虚拟内存概念、请求分页管理方式、页面分配策略、页面置换算法
、页面分配策略、工作集和抖动。
看这里

如何保证线程安全

判断线程安全:
1.多个线程同时对操作临界资源而不会出现数据二义性
2.在线程中对临界资源进行了非原子操作
如何解决:
使多个线程对临界资源的访问是安全的。
实现 :同步与互斥

同步 :多个线程按照某种规则,实现对临界资源访问的合理性
互斥:同一时间只有一个线程能访问临界资源,实现资源访问的安全。

同步实现 : 条件变量、信号量
互斥实现:互斥锁

网络

讲一下三次握手和四次挥手

三次握手

在这里插入图片描述

四次挥手

在这里插入图片描述

讲一下为什么是三次握手?而不是两次握手或者四次握手?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

为什么建立连接要三次握手,释放连接的时候要四次

1、当主机A确认发送完数据且知道B已经接受完了,想要关闭发送数据口(当然确认信号还是可以发),就会发FIN给主机B。

2、主机B收到A发送的FIN,表示收到了,就会发送ACK回复。

3、但这是B可能还在发送数据,没有想要关闭数据口的意思,所以FIN与ACK不是同时发送的,而是等到B数据发送完了,才会发送FIN给主机A。

4、A收到B发来的FIN,知道B的数据也发送完了,回复ACK, A等待2MSL以后,没有收到B传来的任何消息,知道B已经收到自己的ACK了,A就关闭链接,B也关闭链接了。

详解

tcp如何保证安全?

这里
在这里插入图片描述

tcp如何保证效率?

在这里插入图片描述

常见http状态码

在这里插入图片描述
常见状态码
499是由于超过客户端设置的请求超时时间,客户端主动关闭连接,服务器code为499。

500多是由于代码语法错误,导致CGI执行错误并且会把错误结果通知服务器,服务器则报500。

502是由于CGI由于在自身的执行时间要求内无法按时完成,则无法返回给服务器正常响应,此时服务器会返回502。

504是CGI在服务器设置的超时时间内无法按时返回响应,服务器则返回504。

499,502,504都会因为超时而产生,区别是超时超了谁的时,499是超了客户端本身的连接时间,502是超了CGI的执行时间,504是超了服务器本身的最大允许读取时间。

长短链接区别和适用场景

短链接:
短连接:指的是client端与server端进行通信时,此时先三次握手,建立连接,然后client端向服务器发送请求,服务器回复,此时进行四次挥手,断开连接。早期使用短连接,拿网页来说,早期的网页数据量较小,一次可以发送完,所以采用短连接可以做到管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段http 0.9
长连接:
client向server发起连接,server接受client连接,双方建立连接。Client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。
首先说一下TCP/IP详解上讲到的TCP保活功能,保活功能主要为服务器应用提供,服务器应用希望知道客户主机是否崩溃,从而可以代表客户使用资源。如果客户已经消失,使得服务器上保留一个半开放的连接,而服务器又在等待来自客户端的数据,则服务器将应远等待客户端的数据,保活功能就是试图在服务器端检测到这种半开放的连接。
如果一个给定的连接在两小时内没有任何的动作,则服务器就向客户发一个探测报文段,客户主机必须处于以下4个状态之一:
1.客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。
2.客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
3.客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。
4.客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探查的响应

适用情况
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。
短连接:
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

简述http的生命周期

看这里

在浏览器输入一个url,回车后都经历了什么?

看这里

tcp链接与释放的过程,与udp的区别

tcp链接与释放的过程,与udp的区别(为什么是3次握手,4次挥手)
同上~~

一次tcp链接能发送多少次http请求(http1 http1.1 http2 的区别与联系)

1.http 1.0
默认一次tcp连接进行一次http请求之后就会断开(由于资源浪费,有些服务器支持通过配置支持多次)
2.http 1.1
请求头配置:Connection:keep-alive = true,只要tcp连接不断开(默认2小时),一直可以进行http请求,但是一个tcp连接同一时间只支持一个http请求
Connection:keep-alive = false,只能发一次http请求
3.http 2.0:多路复用技术Multiplexing,一个tcp可以并发多个http请求(理论无上限,但是一般浏览器会有tcp并发数的限制)

DNS解析

dns 应用层协议

ARP协议

arp

TCP协议如何提供安全可靠的服务?

看这里

简述下I/O多路复用技术

看这里就行

五层、七层网络模型

在这里插入图片描述

http

在这里插入图片描述

http与https区别

安全性上,HTTPS是安全超文本协议,在HTTP基础上有更强的安全性。简单来说,HTTPS是使用TLS/SSL加密的HTTP协议
申请证书上,HTTPS需要使用ca申请证书
传输协议上, HTTP是超文本传输协议,明文传输;HTTPS是具有安全性的 SSL 加密传输协议
连接方式与端口上,http的连接简单,是无状态的,端口是 80; https 在http的基础上使用了ssl协议进行加密传输,端口是 443
看这里

https的加密是怎么完成的?对称加密和非对称加密的区别?为什么要非对称加密呢?

对称加密:
在这里插入图片描述
缺点:容易被中间劫持,无法保证拿到的公钥是真正的服务器发给它的。
在这里插入图片描述
https底层采用的
在这里插入图片描述
非对称加密:
加密与解密采用不同的密钥。
在这里插入图片描述
在这里插入图片描述
非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人–银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。
特性:
(1) 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。
(2) 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
(3) 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

https

在这里插入图片描述

tcp /udp区别

udp
无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
面向数据报: 不能够灵活的控制读写数据的次数和数量;
(1)TCP是面向连接的,而UDP是无连接的;
TCP发送数据前先要建立连接,而UDP发送数据前不需要建立连接。
(2)TCP保证可靠性,UDP不保证可靠性;
TCP具有很多的可靠性保证机制(TCP的连接管理、超时重传、序号和确认序号、流量控制和拥塞控制都能保证TCP数据包能够无差错、不丢失、按序到达),但是UDP没有这些可靠性保证机制,因此UDP就无法保证可靠性。
(3)TCP面向字节流,UDP面向数据报;
TCP接收和发送数据就像流水一样,可以一次接收多个,或者一次接收少半部分但是可以接收多次;但是UDP发送多少就要接收多少,如果接收的数据少于发送的数据,那么少的那部分数据永远也接收不到了。
(4)每一条TCP连接只能用于点点之间一对一进行,而UDP支持一对一、一对多、多对多的交互通信;
(5)TCP不仅有接收缓冲区还有发送缓冲区,而UDP只有接收缓冲区。

epoll中的LT模式与ET模式区别

在这里插入图片描述

DNS协议?DNS劫持

在这里插入图片描述

在这里插入图片描述
DNS协议:
DNS协议则是用来将域名转换为IP地址(也可以将IP地址转换为相应的域名地址)。
DNS劫持:
一般而言,用户上网的DNS服务器都是运营商分配的,所以,在这个节点上,运营商可以为所欲为。

例如,访问http://jiankang.qq.com/index.html,正常DNS应该返回腾讯的ip,而DNS劫持后,会返回一个运营商的中间服务器ip。访问该服务器会一致性的返回302,让用户浏览器跳转到预处理好的带广告的网页,在该网页中再通过iframe打开用户原来访问的地址。

HTTP 1.0,1.1 对比

http各个版本对比

讲一下select和epoll区别?(腾讯一面)

在这里插入图片描述

数据库

常见问题

char和varchar有什么区别

1.char的长度是不可变的,而varchar的长度可变。
2.定义char长度为10,存入‘qwe’也会占用10的长度并使用空格补齐,而varchar不会。
3.char的存取速度更快,因为其长度固定,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固 定,所以难免会有多余的空格占位符占据空间,可谓是以空间换取时间效率,而varchar是以空间效 率为首位的。
4.char的存储方式是,对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节;而varchar的存 储方式是,对每个英文字符占用2个字节,汉字也占用2个字节,两者的存储数据都非unicode的字 符数据

内外连接的区别

内连接:指连接结果仅包含符合连接条件的行,参与连接的两个表都应该符合连接条件。
外连接:连接结果不仅包含符合连接条件的行同时也包含自身不符合条件的行。包括左外连接、右外连接和全外连接。
左外连接:左边表数据行全部保留,右边表保留符合连接条件的行。
右外连接:右边表数据行全部保留,左边表保留符合连接条件的行。
全外连接:左外连接 union 右外连接。

mvcc 多版本并发控制

mvcc

索引

索引的类型有哪些

主键索引(primary key)
唯一索引(unique)
普通索引(index)
全文索引(fulltext)–解决中子文索引问题

底层实现(B+树介绍)

聚簇索引与非聚簇索引区别?

聚簇索引:索引+数据
非聚簇索引:索引+地址 需要一次回表

mysql存储引擎有哪些,有什么区别,锁有哪些?

在这里插入图片描述
mysql锁

myisam与innode存储引擎区别

在这里插入图片描述
在这里插入图片描述

事务

MySQL事务的四大特性

事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。
事务被 MySQL 编写者设计出来,本质是为了当应用程序访问数据库的时候,事务能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题.可以想一下当我们使用事务时,要么提交,要么回滚,我们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服务的.而不是伴随着数据库系统天生就有的.
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交
( read committed )、可重复读( repeatable read )和串行(Serializable )
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

MySQL事务的隔离级别

在这里插入图片描述

海量数据

给定40亿数据,判断没有出现的唯一数据

在这里插入图片描述

百万数据找前100个

项目问题解决思路

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

范式Huffman树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值