后台开发相关知识(整理自用)

基础语言

  • 指针数组和数组指针

    指针数组本质是数组,数组的每个元素存放的是一个指针类型的元素。int* arr[8].

    优先级说明:[]的优先级比*高

    arr是一个数组,而int*是数组里面的内容

    这句话的意思是:arr是一个含有8个int*的数组

    数组指针本质是指针。该指针指向一个数组.int (*arr)[8]

    由于[]的优先级比*高,因此在写数组指针是必须将arr用括号括起来

    arr先和星号结合,说明p是一个指针变量

  • 字符数组和字符串常量

    char arr[]=“hello”; //字符数组

    char *arr2=“hello”; //字符串常量

    • char arr[]=“hello”,此处的赋值是将常量区的字符串"hello"拷贝到了堆栈区的数arr的空间了。数组arr是在堆栈区开辟了空间,此时是可以修改字符串的值,因为修改的是堆栈区的字符串的值。另外此时的数组名p是堆栈区中的"hello"的首地址。
    • char *arr2=“hello”,指针arr2是存储在堆栈区,但字符串是常量,存储在常量区,只是指针arr指向了存储在常量区的字符串首地址,此时不能改变常量区的字符串的值。

    const char arr[]=“hello”; //这里hello本来是在栈上的,但是编译器可能会做某些优化,将其放到常量区 const char *arr2=“hello”; //字符串hello保存在常量区,const本来是修饰arr2指向的值不能通过arr2去修改,但是字符串hello在常量区,本来就不能改变,所以加不加const效果都一样。

  • 指针和引用的区别
    • **指针有内存分配,而引用只是一个别名。**引用声明时必须初始化,从而指向一个已经存在的对象。
    • **引用可以看作常量指针,指针是一个存储地址的变量。**指针在运行时乐意改变其所指向的值,而引用一旦和某个对象绑定后就不再改变。这句话可以理解为:指针可以被重新赋值以指向另一个不同的对象,但是引用则总是指向在初始化时被指定的对象以后不能改变,但是指定的对象其内容可以改变。
    • **引用创建时必须初始化,且不为空,指针创建时可以为空。**不存在只想控制的引用这一事实,意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空。
    • 指针和引用的自增运算符意义不同。指针是对内存地址的自增没引用是对值得自增。
    • sizeof的意义不同。使用sizeof看一个指针的大小时4,而引用语被引对象有关。
    • 没有引用常量,有指针常量。没有int& const p,有int* const p. 常量指针和常量引用是存在的,const int *p和cosnt int &p,都表示指向的对象为常量。常量引用形参的好处:(1)使用引用作为形参,不会产生新的变量,减少形参和实参传递的开销;(2)使用引用可能会导致实参随着形参的改变而改变。声明为const之后就会消除这种副作用。
    • 参数传递。作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引用的修改都会改变引用所指向的对象
    • 多级指针,一级引用.指针可以嵌套**p,引用只有一级
  • C++中的class和struct
    • 默认的继承访问权限。struct是public的,class是private的。class B:public A就是为了知名是public继承,而不是用默认的private继承,class B:A是private继承。
    • 定义模板参数。class这个关键字还用于定义模板参数,就像typename。但关键字struct不用于定义模板参数。
  • new/delete和malloc/free区别
    • 属性不同.new/delete是c++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持c
    • 申请的内存所在位置。new操作符从自由存储区(free store)上为对象动态分配内存空间。而malloc函数从堆上动态分配内存。
    • 返回类型安全性。new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配。无需进行类型转换,故new是符合类型安全性的操作符。而malloc分配内存成功返回void*类型,需要通过强制类型转换将空类型指针转换成我们需要的类型。
    • 内存分配失败时的返回值。new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。
    • 是否需要指定内存大小。使用new操作符申请内存分配时无需指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要现实的指出所需内存的大小
  • 面向对象和面向过程的区别

面向对象就是高度实物抽象化、面向过程就是自顶向下的编程

  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用
  • 面向对象是把要解决的问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为
  • 面向过程的优缺点 1. 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。 2. 缺点:没有面向对象易维护、易复用、易扩展
  • 面向对象的优缺点 1. 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 2. 缺点:性能比面向过程低

面向对象就是高度实物抽象化、面向过程就是自顶向下的编程

  • 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用
  • 面向对象是把要解决的问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为
  • 面向过程的优缺点 1. 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。 2. 缺点:没有面向对象易维护、易复用、易扩展
  • 面向对象的优缺点 1. 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 2. 缺点:性能比面向过程低。
  • const关键字
    • 修饰变量,说明该变量不可以被改变
    • 修饰指针,分为指向常量的指针和指针常量;int *const p和const int *p
    • 常量引用,经常用于形参类型,即避免了拷贝,又避免了函数对值的修改;
    • 修饰成员函数,说明该成员函数内不能修改成员变量,本质是const this指针。
  • static关键字(对外不可见)
  • 修饰普通变量, 修改变量的存储区域和生命周期,使变量存储在静态区,在 main 函数运行前就分配了空间,在整个程序运行期间一直存在,如果有初始值就用初始值初始化它,如果没有初始值系统用默认值初始化它,自动初始化为0。 全局变量作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。 局部变量作用域:仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它进行访问,直到该函数再次被调用,并且值不变;
  • 修饰普通函数, 其只能在定义它的源文件中使用,不能在其他源文件中被引用
  • 修饰类成员变量和成员函数, 它们是属于类的,而不是某个对象,所有对象共享一个静态成员。静态成员通过<类名>::<静态成员>来使用。在 static 函数内不能访问非静态成员
  • extern关键字

    extern关键字主要修饰变量或函数,表示该函数可以跨文件访问,或者表明该变量在其他文件中定义,在此处引用。

    在c头文件中通过#ifdef…#endif来定义。在cpp文件中通过“extern “C” 函数名”调用,或者包含c头文件 注意: extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间,但若需要调用的函数太多,还是直接包含头文件吧。

  • volatile关键字
    • 不可优化性. volatile 关键字是一种类型修饰符,用它声明的类型变量表示不可以被某些编译器未知的因素(操作系统、硬件、其它线程等)更改。所以使用 volatile 告诉编译器不应对这样的对象进行优化。
    • 易变性. volatile 关键字声明的变量,每次访问时都必须从内存中取出值(没有被 volatile 修饰的变量,可能由于编译器的优化,从 CPU 寄存器中取值)
  • explicit关键字

    防止对象间实现=赋值,防止类构造函数的隐式自动转换,类构造函数默认情况下即声明为implicit(隐式),另外explicit只用于单参数的构造函数,或者除了第一个参数外其他参数都有默认值。

  • 构造函数/析构函数

    构造函数和析构函数,分别对应变量的初始化和清理,变量没有初始化,使用后果未知;没有清理,则会内存管理出现安全问题。当对象结束其生命周期,如对象所在的函数已经调用完毕时,系统会自动执行析构函数。

    • 构造函数:与类名相同,没有返回值,不写void,可以发生重载,可以有参数,编译器自动调用一次。
    • 析构函数:~类名,没有返回值,不写void,不可以发生重载,不可以有参数,编译器自动调用一次。

数据结构

  • 二叉树基础
    • 定义

      n个结点的有限集合。该集合为空集,或者是一个根节点和两颗互不相交的、分别成为根节点的左子树和右子树的二叉树组成。

    • 满二叉树

      一棵二叉树中所有分支结点都存在左子树和右子树,所有叶子都在同一层上。

    • 完全二叉树

      一颗有n个结点的二叉树按层序编号,编号为i的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同。

  • 最大堆和最小堆
    • 最大堆

      每个结点的值豆大于等于其左右孩子结点的值

    • 最小值

      每个结点的值都小于等于其左右孩子结点的值

  • 二分查找
    • 适用于有序数组

    • 查找时间复杂度O(nlogn).

  • 二叉排序树
    • 查找时间复杂度O(nlogn),最坏情况变成右斜树O(n).

    • 若左子树不为空,则左子树上所有结点的值小于根节点的值

    • 若右子树不为空,则右子树上所有结点的值大于根节点的值

  • 哈希表

    哈希表是一种以键-值存储数据的结构,我们只要输入待查找的值,即可找到其存储位置。

    • 哈希表的实现

      使用哈希函数将被查找的键转换为数组的索引。方法有直接地址法、平方去中法、除留余数法。理想的情况下,不同的键会被转换为不同的索引值,但是在有些情况下我们需要处理多个键被哈希到同一个索引值的情况。所以哈希查找的第二个步骤就是处理冲突。有很多处理了哈希碰撞冲突的方法,如拉链法、线性探测法、再哈希法,公共溢出区法。

      • 构造哈希

        直接地址法:直接用key或key的线性函数值作为索引。如果所有的键值都是整数,那么就可以使用过一个简单的无需数组来实现:将键作为索引,值即为其对应得值,这样就可以快速访问任意键的值。

        平方取中法:将key平方后取中间的几位数作为索引,可以是3位或4位。

        除留余数法:最常用的构造哈希函数的方法,直接对key取模,也可以平方后取模。获取正整数哈希值最常用的方法是使用除留余数法,即对于大小为素数M的数组,对于任意正整数k,计算k除以M的余数。M一般取素数

      • 处理哈希冲突

        拉链法(哈希桶法)

        基本思想

        将大小为M的数组的每一个元素指向一个链表,链表中的每一个结点都存储散列值为该索引的键值对。注意选择足够大的M,使得所有的链表都尽可能的短小,以保证查找的效率

        拉链法查找

        根据散列值找到索引对应的链表,

        沿着链表顺序找到相应的键

        线性探测法(开放定址法)

        基本思想:f(key) = (f(key) + d) MOD M

        线性探测

        当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1

        二次探测

        索引值位移量不为1,为1,-1,2,-2…的平方

        随机探测

        索引值位移量采用随机函数计算得到。随机种子产生伪随机数,每次得到的随机序列相同

        再哈希法

        使用哈希函数去散列一个输入的时候,输出是同一个位置就再次散列,直至不发生冲突位置,但每次冲突都要重新散列,计算时间增加,另外需要准备多个哈希函数

        公共溢出区法

        建立一个公共溢出区域,把hash冲突的元素都放在该溢出区里。查找时,如果发现hash表中对应桶里存在其他元素,还需要在公共溢出区里再次进行查找。

  • 赫夫曼树

    从树中一个结点到另一个结点之间的分支构成两个节点之间的路径,路径上的分支数目称为路径长度,为结点数-1。树的路径长度是从树根到每一个结点的路径长度之和。

    带权路径长度:若结点带权,则带权路径长度为改结点到树根之间的路径长度与结点上权重的乘积。

    赫夫曼树:带权路径长度WPL(weight path length) 最小的二叉树为赫夫曼树。

计算机网络

OSI七层协议及TCP/IP四层协议

  • 七层协议:物、数、网、传、会、表、应
    • 物理层 RJ45
    • 数据链路层 PPP,IEEE 802.3/802.2
    • 网络层 IP,ARP
    • 传输层 TCP,UDP
    • 会话层
    • 表示层 TIFF,GIF,JPEG,
    • 应用层 DNS,HTTP,FTP
  • 四层协议:数据链路层(物理层,数据链路层),网络层(网络层),传输层(传输层),应用层(会话层,表示层,应用层)
    • 数据链路层: PPPMAC不属于协议,只是一个地址
    • 网络层:IP、ARP、ICMP
    • 传输层:TCP、UDP
    • 应用层:DNS、HTTP、FTP

通信交互方式

  • 单工通信
    • 只能有一个方向的通信没有反方向的交互
  • 半双工通信
    • 双方可以发送消息,但不能同时发送。可以交替进行一方发送、另一方接收
  • 全双工通信
    • 通信的双方可以同时发送和接收信息

MAC地址和IP地址

  • MAC地址又叫硬件地址或物理地址,它不是地址位置,实际上是适配器地址,每一台计算机中固化在适配器的ROM中的地址,作用是用来定义网络设备的位置
  • IP地址是IP协议提供的一种统一的地址格式,为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异
  • 两者的区别
    • 物理地址是数据链路层和物理层使用的地址,放在MAC帧的首部
    • IP地址是网络层和以上各层使用的地址,放在IP数据报的首部

ARP协议的作用

网络层使用的是IP地址,数据链路层使用的是硬件地址。 ARP协议的用途是为了从网络层使用的IP地址,解析出数据链路层使用的硬件地址。

  • 在主机ARP高速缓存中存放一个从IP地址到硬件地址的映射表
  • 当需要解析时,先去arp缓存表(存着ip-mac对应关系)去查找目标ip的mac地址
  • 如果查到了,将目标ip的mac地址封装到链路层数据报
  • 如果缓存中没有找到,会发起一个广播:who is ip XXX tell ip XXX,所有收到的广播的机器看这个ip是不是自己的,如果是自己的,则以单播的形式将自己的mac地址回复给请求的机器

ping发生了什么

ping主要是为了测试两台主机之间的连通性,通过应用层直接使用网络层ICMP,没有通过运输层TCP和UDP,是通过发送ICMP报文回显请求实现。

  • A主机构建一个ICMP格式的数据包,通过ICMP协议把该数据包和B主机的IP地址一起交给IP协议;
  • IP层构建一个数据包(A主机的IP地址+控制信息+B主机的IP地址),获得B主机的MAC地址,以便构建一个数据帧(IP协议会根据B主机的IP地址和自己的子网掩码判断是不是属于同一层网络,如果是属于同一层网络的话,就会获得B主机的MAC地址,如果以前两机有过通信,在A机的ARP缓存表应该有B机IP与其MAC的映射关系,如果没有,就发一个ARP请求广播,得到B机的MAC)
  • 主机B接受到主机A的发过来的数据帧以后,先检查该帧中包含的B的IP地址,并和本地的物理地址进行比对,如果符合的话,就接受,否则,就抛弃。同样,需要将该数据帧交由自己的IP层协议,IP层检查以后,再交由ICMP协议,构建一个ICMP的应答包,发送给主机A。

traceroute发生了什么

traceroute用来跟踪一个分组从源点到终点的路径,及到达其中每一个路由器的往返时间

  • 通过发送UDP报文,设置目的端口为一个不可能的值
  • 将IP首部中的TTL分别设置从1到N,每次逐个增加
  • 每次设置TTL后,重新发送数据报,路由器接收到数据报后,将TTL减1,若当前的路由器接收到数据报,发现TTL为1时,会将TTL减1变为0,然后丢弃数据报,发送ICMP时间超过报文
  • 如果最后一个数据报刚刚达到主机,数据报的TTL是1,此时主机不把TTL减1
  • 因IP数据报中封装的是无法交付的UDP数据报,此时目的主机向源主机发送ICMP终点不可达差错报文,表示达到目的主机

TCP/UDP的区别和应用场景

###区别 TCP,全称:传输控制协议,面向连接的安全的流式传输协议 UDP,全称:用户数据报协议,面向无连接的不安全的报式传输协议

  • 连接
    • TCP是面向连接的传输层协议,即传输数据之前必须先建立好连接。
    • UDP无连接。
  • 服务对象
    • TCP是点对点的两点间服务,即一条TCP连接只能有两个端点
    • UDP支持一对一,一对多,多对一,多对多的交互通信。
  • 可靠性
    • TCP是可靠交付:无差错,不丢失,不重复,按序到达。
    • UDP是尽最大努力交付,不保证可靠交付。
  • 拥塞控制,流量控制
    • TCP有拥塞控制和流量控制保证数据传输的安全性。
    • UDP没有拥塞控制,网络拥塞不会影响源主机的发送效率。
  • 报文长度
    • TCP是动态报文长度,即TCP报文长度是根据接收方的窗口大小和当前网络拥塞情况决定的,流式传输
    • UDP面向报文,不合并,不拆分,保留上面(应用层)传下来报文的边界,直接传输报文。
  • 首部开销
    • TCP首部开销大,首部20个字节。
    • UDP首部开销小,8字节。(源端口,目的端口,UDP数据报长度,检验和,每个字段两个字节)
应用场景
  • 要求通信数据完整性,则应该选用TCP协议(如文件传输、重要状态的更新,登录数据传输等)
  • 要求通信实时性,使用 UDP 协议(如视频传输,通话,屏幕共享软件)

拥塞控制和流量控制的区别

  • 拥塞控制是防止过多的数据注入到网络中,可以使网络中的路由器或链路不致过载,是一个全局性的过程。
  • 流量控制是点对点通信量的控制,是一个端到端的问题,主要就是抑制发送端发送数据的速率,以便接收端来得及接收

TCP滑动窗口实现流量控制

  • 流量控制是让发送方的发送速率不要太快,要让接收方来得及接收,实现对发送方的流量控制.
  • 滑动窗口出现的原因:在确认应答策略中,对每一个发送的数据段,都要给一个ACK确认应答,收到ACK后再发送下一个数据段,这样做有一个比较大的缺点,就是性能比较差,尤其是数据往返的时间长的时候
  • 滑动窗口以字节为单位,而不是报文

TCP超时重传

  • 保证了数据的可靠传输,对于一些出错,丢包等问题TCP设计了超时与重传机制。
  • 基本原理:在发送一个数据之后,就开启一个定时器,并设置RTO,若是在这个时间内没有收到发送数据的ACK确认报文,则对该报文进行重传,在达到一定次数还没有成功时放弃并发送一个复位信号。
  • 不同的网络情况不一样,不可能设置一样的RTO(超时重传时间),实际中RTO是根据网络中的RTT(报文段往返时间)来自适应调整的

TCP拥塞机制

  • 拥塞的标志
    • 超时重传
    • 3次重复的ACK

慢启动,拥塞避免,快恢复,快重传

ACK SYN FIN解释及是否消耗序列号

  • ACK 确认标志位,ACK可以携带数据,若不携带,则不消耗序列号
  • SYN 同步标志位,SYN不能携带数据,必须消耗一个序列号
  • FIN 终止标志位,FIN可以携带数据,必须消耗一个序列号

TCP三次握手及三次缘由

  • 为什么TCP三次握手,不能两次或者四次吗?
    • 三次握手是为了防止,客户端的请求报文在网络滞留,客户端超时重传了请求报文,服务端建立连接,传输数据,释放连接之后,服务器又收到了客户端滞留的请求报文,建立连接一直等待客户端发送数据。
    • 服务器对客户端的请求进行回应(第二次握手)后,就会理所当然的认为连接已建立,而如果客户端并没有收到服务器的回应呢?此时,客户端仍认为连接未建立,服务器会对已建立的连接保存必要的资源,如果大量的这种情况,服务器会崩溃。
    • 服务器端给客户端发送同步及确认报文时可以合并,四次会浪费时间

TCP四次挥手及四次缘由

四次报文中服务器端发送给客户端的请求关闭连接报文FIN和ACK也是合并的,相对于三次来说,只是前面多了一次ACK的确认。

  • 为什么TCP四次挥手,不能三次吗?
    • 当客户端确认发送完数据且知道服务器已经接收完了,想要关闭发送数据口(当然确认信号还是可以发),就会发FIN给服务器。
    • 服务器收到客户端发送的FIN,表示收到了,就会发送ACK回复。
    • 但这时候服务器可能还在发送数据,没有想要关闭数据口的意思,所以服务器的FIN与ACK不是同时发送的,而是等到服务器数据发送完了,才会发送FIN给客户端。
    • 客户端收到服务器发来的FIN,知道服务器的数据也发送完了,回复ACK, 客户端等待2MSL以后,没有收到服务器传来的任何消息,知道服务器已经收到自己的ACK了,客户端就关闭链接,服务器也关闭链接(服务器比客户端早关闭)。

TIME-WAIT状态及2MSL时间

  • 四次挥手期间,客户端和服务器端都可主动释放连接,谁主动释放,谁将进入TIME_WAIT状态
  • MSL是最长报文寿命,一般为2分钟,2MSL即4分钟
  • 为什么TIME-WAIT状态必须等待2MSL时间?
    • **保证最后一次挥手报文能到B,能进行超时重传。**若B收不到A的ACK报文,则B会超时重传FIN+ACK,A会在2MSL时间内收到重传报文段,然后发送ACK,重新启动2MSL计时器
    • 2MSL后,本次连接的所有报文都会消失,不会影响下一次连接。

域名系统DNS

用于将域名转换为IP地址。 DNS解析过程有两种,分别是递归查询和迭代查询。

  • 递归查询
    • 若主机询问的本地域名服务器不知道被查询域名的IP地址,本地域名服务器以DNS客户身份,向其他根域名服务器继续发出查询请求报文(代替该主机继续查询),而不是该主机自己进行下一步查询
  • 迭代查询
    • 当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出IP地址,要么告诉本地域名服务器,应该向哪一个域名服务器进行查询,然后本地域名服务器进行后续查询

统一资源定位符URL

统一资源定位符URL,用来表示从互联网上得到的资源位置。

  • 一般由四个部分组成
    • <协议>://<主机>:<端口>/<路径>
    • 主机一般为域名,需要通过DNS系统解析出IP
  • 使用HTTP的URL
    • http://<主机>:<端口>/<路径>

描述一下HTTP协议

概述
  • HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议。
  • HTTP属于应用层协议,基于TCP/IP通信协议来传递数据
特点
  • 灵活
    • HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  • 无连接
    • 无连接的含义是通信双方在交换HTTP报文之前不需要建立HTTP连接
  • 无状态
    • 无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时应答较快。
  • 支持B/S和C/S模式
  • 默认端口80
  • 基于TCP协议
HTTP工作原理

HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。

  • 客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。
  • 服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。

HTTP 请求/响应的步骤

  • 客户端连接到Web服务器 一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.oakcms.cn。
  • 发送HTTP请求 通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
  • 服务器接受请求并返回HTTP响应 Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
  • 释放连接TCP连接 若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
  • 客户端浏览器解析HTML内容 客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

HTTP2

  • 新的二进制格式(Binary Format)
    • HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
  • 多路复用(MultiPlexing)
    • 即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
    • pipelining在接收response返回时,必须依顺序接收,如果前一个请求遇到了阻塞,后面的请求即使已经处理完毕了,仍然需要等待阻塞的请求处理完毕。这种情况就如图中第三种,第一个请求阻塞后,后面的请求都需要等待,这也就是队头阻塞
  • header压缩
    • 对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小
  • 服务端推送
    • 我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了

HTTP持久连接与管线化

HTTP协议首先要和服务器建立TCP连接,这需要三次握手。

  • 请求一个万维网文档的时间
    • 当建立TCP连接的三次握手前两次完成后,即经过一个RTT时间,万维网客户就把HTTP请求报文,作为建立TCP连接的三次握手中的第三次的数据,发送给万维网服务器,服务器收到HTTP请求后,把请求的文档作为响应报文返回给客户。
    • 文档传输时间+2*RTT
  • HTTP1.0非持久连接的缺点
    • 每请求一个文档,需要两倍RTT的开销。服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接,然后重新建立连接发出请求
  • HTTP1.1持久连接
    • 万维网服务器在发送响应后仍然在一段时间内保持这段连接,可以使得同一用户继续在该连接上传送后续请求和响应报文
  • 持久连接的两种工作方式
    • 非管线化
      • 发送请求后需等待并收到回应,才能发送下一个请求
    • 管线化
      • 不用等待响应,直接发送下一个请求,但接收的时候必须按照顺序接收,如果有一个请求阻塞,则接收会全部阻塞

HTTP协议请求报文具体信息

HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据四个部分组成

  • GET

    GET /562f25980001b1b106000338.jpg HTTP/1.1
    Host:img.mukewang.com
    User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64)
    AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
    Accept:image/webp,image/*,*/*;q=0.8
    Referer:http://www.imooc.com/
    Accept-Encoding:gzip, deflate, sdch
    Accept-Language:zh-CN,zh;q=0.8
    空行
    请求数据为空
    
  • POST

    POST / HTTP1.1
    Host:www.wrox.com
    User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
    Content-Type:application/x-www-form-urlencoded
    Content-Length:40
    Connection: Keep-Alive
    空行
    name=Professional%20Ajax&publisher=Wiley
    
  • 请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本. GET说明请求类型为GET,/562f25980001b1b106000338.jpg(URL)为要访问的资源,该行的最后一部分说明使用的是HTTP1.1版本。
  • 请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息 * HOST,给出请求资源所在服务器的域名. * User-Agent,HTTP客户端程序的信息,该信息由你发出请求使用的浏览器来定义,并且在每个请求中自动发送等 * Accept,说明用户代理可处理的媒体类型 * Accept-Encoding,说明用户代理支持的内容编码 * Accept-Language,说明用户代理能够处理的自然语言集 * Content-Type,说明实现主体的媒体类型 * Content-Length,说明实现主体的大小 * Connection,连接管理,可以是Keep-Alive或close
  • 空行,请求头部后面的空行是必须的即使第四部分的请求数据为空,也必须有空行。
  • 请求数据也叫主体,可以添加任意的其他数据。

GET和POST区别

GET /books/?sex=man&name=Professional HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
空行
请求数据为空
  • 区别

    • get参数通过url传递,post放在request body中,GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变

    • POST的安全性要比GET的安全性高,一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

    • get请求在url中传递的参数是有长度限制的,而post没有

    • GET产生一个TCP数据包,POST产生两个TCP数据包

      • 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
      • 对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)

HTTP协议响应报文具体信息

HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

HTTP/1.1 200 OK
Date: Fri, 22 May 2009 06:07:21 GMT
Content-Type: text/html; charset=UTF-8
<html>
      <head></head>
      <body>
            <!--body goes here-->
      </body>
</html>
  • 状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。 第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为OK
  • 消息报头,用来说明客户端要使用的一些附加信息 第二行和第三行为消息报头,Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8
  • 空行,消息报头后面的空行是必须的
  • 响应正文,服务器返回给客户端的文本信息。空行后面的html部分为响应正文

HTTP状态码

  • 1xx:指示信息–表示请求已接收,继续处理。
  • 2xx:成功–表示请求正常处理完毕。
    • 200 OK:客户端请求被正常处理
    • 206 Partial content:客户端进行了范围请求
  • 3xx:重定向–要完成请求必须进行更进一步的操作。
    • 301 Moved Permanently:永久重定向,该资源已被永久移动到新位置,将来任何对该资源的访问都要使用本响应返回的若干个URI之一
    • 302 Found:临时重定向,请求的资源现在临时从不同的URI中获得
  • 4xx:客户端错误–请求有语法错误,服务器无法处理请求。
    • 400 Bad Request:请求报文存在语法错误
    • 403 Forbidden:请求被服务器拒绝
    • 404 Not Found:请求不存在,服务器上找不到请求的资源
  • 5xx:服务器端错误–服务器处理请求出错。
    • 500 Internal Server Error:服务器在执行请求时出现错误
    • 503 Service Unavaliable:服务器正在停机维护

浏览器键入URL后的访问流程

  • 浏览器使用DNS协议向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址,其中DNS服务器是基于UDP的,因此会用到UDP协议;
  • 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接,会使用到TCP协议;
  • 然后浏览器就要与服务器建立一个http连接,因此要用到http协议,http生成一个get请求报文,如果采用https还会使用https协议对http数据进行加密,涉及到SSL协议,将报文发送到TCP层
  • TCP层如果有需要先将HTTP数据包分片,分片依据MTU和MSS( mtu是网络传输最大报文包,mss是网络传输数据最大值)。
  • TCP的数据包然后会发送给IP层,用到IP协议。IP层通过路由选路,一跳一跳发送到目的地址。
  • 当然在一个网段内的寻址是通过以太网协议实现,以太网协议需要知道目的IP地址的物理地址,则需要ARP协议
  • 服务器端接收到请求,然后发送返回响应请求
  • 释放 TCP连接(若connection为close,则释放TCP连接,若为keep-alive则不会释放);
  • 浏览器将该解析html文本并显示内容

IP/TCP/UDP分片

数据发送时,将数据从应用层->传输层->网络层->数据链路层,其中传输层是TCP和UDP,网络层是IP协议。

  • MTU以太网帧的长度为1500字节,所能接收的传输层数据段最大为 1480 个字节(以太网帧中的数据包括 IP 协议的报头信息,IP 协议的报头信息为 20 字节)
  • 在计算 MSS (网络传输数据最大值)的时候,用 MTU 减去网络层报头长度以及传输层报头长度即可。
  • UDP
    • 一旦 UDP 携带的数据超过了 1472 (MTU - IP报头 - UDP报头 = 1500 - 20 - 8),那么在 IP 层就会对该数据分片,一旦分片就意味着增加了 UDP 传输丢包的可能性。 由于 UDP 协议传输本身就不负责可靠性,再加上分片,那么丢包的可能性就大大增加

对称密钥和公钥密码体制

  • 对称密钥密码体制
    • 加密密码和解密密码是相同的密钥
  • 公钥密码体制,非对称加密
    • 加密密码和解密密码不同
    • 加密和解密算法都是公开的,加密密钥也是公开的,解密密钥是保密的
    • 公钥和私钥是配对关系,公钥加密就用私钥解密,反之亦然

数字签名和数字证书

使用公钥密码加密的一般流程:通过A的公钥对报文加密,发送给B,然后B拿A的私钥进行解密,得到报文. 注意:并不是每次传输报文的时候都要加数字签名,数字签名一般用于数字证书的验证,这样的话浏览器内置的CA拥有服务端的公钥和私钥。

  • 数字签名
    • 普通数字签名(能核实发送者,但无法保证报文完整性)
      • A通过A的私钥对报文进行加密,将其附在报文的后面,发送给B,然后B拿A的公钥对附加信息进行解密的过程,为数字签名
      • 上述过程中仅仅实现了数字签名,但并没有对实际报文进行加密。实际操作时,可以通过A–>A私钥(数字签名)–>B公钥(报文加密)–>B私钥(报文解密)–>A公钥(验证数字签名)
    • 密码散列函数
      • 使用密码散列函数对报文进行与运算得到hash值,简称摘要
      • 密码散列函数有MD5和安全散列算法SHA
    • 报文摘要数字签名(核实发送者,保证报文完整性) 对报文本身加密可能是个耗时过程,比如这封Email足够大,那么私钥加密整个文件以及拿到文件后的解密无疑是巨大的开销
      • A先对这封Email执行哈希运算得到hash值简称“摘要”,取名h1
      • 然后用自己私钥对摘要加密,生成的东西叫“数字签名”
      • 把数字签名加在Email正文后面,一起发送给B
      • 防止邮件被窃听你可以用继续B公钥加密
      • B收到邮件后使用B私钥对报文解密,用A的公钥对数字签名解密,成功则代表Email确实来自A,失败说明有人冒充
      • B对邮件正文执行哈希运算得到hash值,取名h2
      • B会对比数字签名的hash值h1和自己运算得到的h2,一致则说明邮件未被篡改。
    • 数字签名的作用
      • 确认核实发送者
      • 保证报文的完整性
      • 一般用于验证数字证书
  • 数字证书 明文和数字签名共同组成了数字证书,这样一份数字证书就可以颁发给网站了,由认证中心(CA)或者认证中心的下级认证中心颁发。通俗来说,A确认收到的公钥真的是B的公钥,而不是别人伪造的
    • 制作数字签名
      • CA拥有非对称加密的私钥和公钥。
      • CA对证书明文信息进行hash。
      • 对hash后的值用私钥加密,得到数字签名
      • 明文和数字签名共同组成了数字证书
    • 数字证书验证过程
      • 拿到证书,得到明文T,数字签名S。
      • 用CA机构的公钥对S解密,得到S’。(由于是浏览器信任的机构,浏览器保有它的公钥,操作系统、浏览器本身会预装一些它们信任的根证书,如果其中有该CA机构的根证书,那就可以拿到它对应的可信公钥)
      • 用证书里说明的hash算法对明文T进行hash得到T’。
      • 比较S’是否等于T’,等于则表明证书可信。

HTTP和HTTPS的区别

  • HTTP协议是以明文的方式在网络中传输数据,而HTTPS协议传输的数据则是经过TLS加密后的,HTTPS具有更高的安全性
  • HTTPS可以保证报文完整性,另外可以核实发送者身份
  • HTTPS协议需要服务端申请证书,浏览器端安装对应的根证书
  • HTTPS在TCP三次握手阶段之后,还需要进行SSL的handshake,协商加密使用的对称加密密钥
  • HTTP协议端口是80,HTTPS协议端口是443

运输层安全协议及SSL工作过程

  • SSL 安全套接字层协议
  • TLS 运输层安全协议,在SSL的基础上设计
  • SSL工作过程
    • 协商加密算法
      • 浏览器A向服务器B发送SSL版本,及自身支持的加密组件(包括加密算法及密钥长度等)
      • B从中选择自身支持的加密组件和SSL版本,发送给A
    • 服务器鉴别
      • B向A发送包含公开密钥的数字证书
      • A对数字证书进行鉴别,获取B的公钥
    • 会话密钥计算
      • A随机产生秘密数,将秘密数通过B的公钥发送给B,之后A通过协商的加密算法产生会话密钥
      • B接收到秘密数后,通过B的私钥将其解密得到秘密数,然后根据协商加密算法产生会话密钥
    • 安全数据传输
      • 双方会互相发送一次数据,用会话密钥加密和解密他们之间传达的数据并验证其完整性
    • 通信
      • 上述验证通过后,才继续进行http通信

HTTPS必须在每次请求中都要先在SSL/TLS层进行握手传输密钥吗?

显然每次请求都经历一次密钥传输过程非常耗时,那怎么达到只传输一次呢?用session就行。

  • 服务器会为每个浏览器(或客户端软件)维护一个session ID,在TSL握手阶段传给浏览器,浏览器生成好密钥传给服务器后,服务器会把该密钥存到相应的session ID下
  • 之后浏览器每次请求都会携带session ID,服务器会根据session ID找到相应的密钥并进行解密加密操作,这样就不必要每次重新制作、传输密钥了!

cookie和session

HTTP协议作为无状态协议,对于HTTP协议而言,无状态指每次request请求之前是相互独立的,当前请求并不会记录它的上一次请求信息,如何将上下文请求进行关联呢?客户端(不同的浏览器)记录用户的状态通过cookie,服务器端(不同的网站)记录用户的状态通过session。

cookie

工作流程
  • 客户端请求服务器端,服务器端产生cookie响应头,随响应报文发送给客户端,客户端将cookie文本保存起来
  • 下次客户端再次请求服务端时,会产生cookie请求头,将之前服务器发送的cookie信息,再发送给服务器,服务器就可以根据cookie信息跟踪客户端的状态。
基础知识

Cookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie,它是服务器端存放在本地机器中的数据,随每一个请求发送给服务器,由于Cookie在客户端,所以可以编辑伪造,不是十分安全。

  • 非持久cookie
    • 内存Cookie由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的。
  • 持久cookie
    • 硬盘Cookie保存在硬盘里,有一个过期时间(客户端cookie设置的时间),除非用户手工清理或到了过期时间,硬盘Cookie不会被删除,其存在时间是长期的。

session

工作流程
  • 当用户第一次访问站点时,服务器端为用户创建一个sessionID,这就是针对这个用户的唯一标识,每一个访问的用户都会得到一个自己独有的session ID,这个session ID会存放在响应头里的cookie中,之后发送给客户端。这样客户端就会拥有一个该站点给他的session ID。
  • 当用户第二次访问该站点时,浏览器会带着本地存放的cookie(里面存有上次得到的session ID)随着请求一起发送到服务器,服务端接到请求后会检测是否有session ID,如果有就会找到响应的session文件,把其中的信息读取出来;如果没有就跟第一次一样再创建个新的。
基础知识

session是存放在服务器里的,所以session 里的东西不断增加会增加服务器的负担,我们会把一些重要的东西放在session里,不太重要的放在客户端cookie里

  • session失效
    • 服务器(非正常)关闭时
    • session过期/失效(默认30分钟)
      • 问题:时间的起算点 从何时开始计算30分钟?从不操作服务器端的资源开始计时(例如:当你访问淘宝页面时,点开页面不动,第29分钟再动一下页面,就得重新计时30分钟;当过了30分钟,就失效了。)
    • 手动销毁session
  • sessionID的传递方式
    • 通过cookie传递
    • 当cookie禁用后,可以通过url传递
  • 不同场景下的session
    • 当在同一个浏览器中同时打开多个标签,发送同一个请求或不同的请求,仍是同一个session;
    • 当不在同一个窗口中打开相同的浏览器时(打开多个相同的浏览器),发送请求,仍是同一个session;
    • 当使用不同的浏览器时,发送请求,即使发送相同的请求,是不同的session;
    • 当把当前某个浏览器的窗口全关闭,再打开,发起相同的请求时,是不同的session。
区别
  • cookie数据存放在客户的浏览器上,session数据放在服务器上。
  • cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
  • 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
  • 可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。

浏览器关闭后,session就销毁了吗?

浏览器关闭和服务器session销毁没有任何关系,会话Cookie(非持久cookie)在关闭浏览器后就会消失,但是原来服务器的Session还在,只有等到了销毁的时间会自动销毁。

后,可以通过url传递

  • 不同场景下的session
    • 当在同一个浏览器中同时打开多个标签,发送同一个请求或不同的请求,仍是同一个session;
    • 当不在同一个窗口中打开相同的浏览器时(打开多个相同的浏览器),发送请求,仍是同一个session;
    • 当使用不同的浏览器时,发送请求,即使发送相同的请求,是不同的session;
    • 当把当前某个浏览器的窗口全关闭,再打开,发起相同的请求时,是不同的session。
区别
  • cookie数据存放在客户的浏览器上,session数据放在服务器上。
  • cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
  • 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
  • 可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。

浏览器关闭后,session就销毁了吗?

浏览器关闭和服务器session销毁没有任何关系,会话Cookie(非持久cookie)在关闭浏览器后就会消失,但是原来服务器的Session还在,只有等到了销毁的时间会自动销毁。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值