网络模型

image-20200211185156724.png
7 层模型主要包括:

  1. 物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率
    等。它的主要作用是传输比特流(就是由 1、0 转化为电流强弱来进行传输,到达目的地后在转化为
    1、0,也就是我们常说的模数转换与数模转换)。这一层的数据叫做比特。
  2. 数据链路层:主要将从物理层接收的数据进行 MAC 地址(网卡的地址)的封装与解封装。常把这
    一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
  3. 网络层:主要将从下层接收到的数据进行 IP 地址(例 192.168.0.1)的封装与解封装。在这一层工
    作的设备是路由器,常把这一层的数据叫做数据包。
  4. 传输层:定义了一些传输数据的协议和端口号(WWW 端口 80 等),如:TCP(传输控制协议,
    传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,
    与 TCP 特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如 QQ 聊天数据就是通过这
    种方式传输的)。 主要是将从下层接收的数据进行分段进行传输,到达目的地址后在进行重组。
    常常把这一层数据叫做段。
  5. 会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间
    发起会话或或者接受会话请求(设备之间需要互相认识可以是 IP 也可以是 MAC 或者是主机名)
  6. 表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够
    识别的东西转换成人能够能识别的东西(如图片、声音等))
  7. 应用层 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(你
    就把它理解成我们在电脑屏幕上可以看到的东西.就 是终端应用)。

    协议

    应用层协议
    SMTP协议:提供可靠且有效的电子邮件传输的协议,端口为25。
    FTP协议:TCP/IP网络上两台计算机传送文件的协议,默认情况下FTP协议使用TCP端口中的 20和21这两个端口,其中20用于传输数据,21用于传输控制信息。
    传输层协议
    telnet协议:用于远程登录,端口号为23。
    网络层协议
    ARP协议:根据IP地址获取物理地址的一个TCP/IP协议。
    ICMP协议:它是TCP/IP协议族的一个子协议,用于在IP主机路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。其中,PING命令的实现原理就是:Ping发送一个ICMP ECHO包,接受ICMP echo(ICMP回声应答)。

    HTTP协议

    超文本传输协议,HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端,位于应用层,并且是无状态的一种协议。

    请求协议

    image-20200229205226968.png
    image-20200229205311421.png

    响应协议

    image-20200229205247818.png
    image-20200229205335851.png

    Http请求方法

  • GET向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
  • POST向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
  • HEAD与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
  • PUT向指定资源位置上传其最新内容。
  • DELETE请求服务器删除Request-URI所标识的资源。
  • TRACE回显服务器收到的请求,主要用于测试或诊断。
  • OPTIONS这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用’*’来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。
  • CONNECTHTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。

    GET和POST的区别

  • GET提交的数据会放在URL之后,也就是请求行里面,以?分割URL和传输数据,参数之间以&相连,如EditBook?name=test1&id=123456;POST方法是把提交的数据放在HTTP包的请求体中。

  • GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
  • GET是不安全的,而POST是安全的。

    TCP协议

    TCP协议的主要功能是完成对数据报的确认、流量控制和网络拥塞;自动检测数据报,并提供错误重发的功能;将多条路径传送的数据报按照原来的顺序进行排列,并对重复数据进行择取;控制超时重发,自动调整超时值;提供自动恢复丢失数据的功能。
    image-20200211190831559.png
  1. URG: 表示紧急指针是否有效。
  2. ACK: 表示确认号是否有效(携带ACK标志的TCP报文段称为确认报文段)。
  3. PSH: 提示接收端应用程序要立即从TCP接收缓冲区读走数据,以腾出空间接收后续的数据。(若应用 程序不读走数据,数据会一直留在TCP模块的接收缓冲区)。
  4. RST: 表示要求对方重新建立连接(携带RST标志的TCP报文段为复位报文段)。
  5. SYN: 表示请求建立一个连接(携带SYN标志的TCP报文段称为同步报文段)。
  6. FIN: 表示通知对方要关闭连接(携带FIN标志的TCP报文段为结束报文段)。

    TCP与HTTP协议的KeepAlive有什么区别

    HTTP位于网络协议栈的应用层,而TCP位于网络协议栈的传输层,两者的KEEP-ALIVE虽然名称相同,但是作用不同。HTTP是为了重用TCP,避免每次请求,都重复创建TCP;而TCP的KEEP-ALIVE是一种保活机制,检测对端是否依然存活。

    TCP协议如何保证传输可靠性

  • 数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时TCP发送数据端超时后会重发数据;
  • 对失序数据包重排序:既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对失序数据进行重新排序,然后才交给应用层;
  • 丢弃重复数据:对于重复数据,能够丢弃重复数据;
  • 应答机制:当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
  • 超时重发:当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
  • 流量控制:TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。TCP使用的流量控制协议是可变大小的滑动窗口协议。

TCP协议通过使用连续ARQ协议和滑动窗口协议,来保证数据传输的正确性,从而提供可靠的传输。

ARQ协议

ARQ协议,即自动重传请求(Automatic Repeat-reQuest),是OSI模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。ARQ包括停止等待ARQ协议和连续ARQ协议,拥有错误检测(Error Detection)、正面确认(Positive Acknowledgment)、超时重传(Retransmission after Timeout)和负面确认及重传(Negative Acknowledgment and Retransmission)等机制。

停止等待ARQ协议

要想弄明白为什么TCP要使用连续ARQ协议,首先需要弄清楚停止等待ARQ协议的原理。
TCP 连接是全双工的连接,也就是说在通信的时候,双方既是发送方,也是接收方。下面为了简化问题,只考虑一方发送,一方接受的情况。其中,A作为发送方,B作为接收方。
1.无差错情况
A发送分组M1,发送完就暂停发送,等待B的确认。B收到M1就向A发送确认。A在收到了对M1的确认后,就再发送下一个分组M2。依次下去发送剩余的数据,如下图所示:
image.png
2.出现差错
如果A发送的过程中出现差错,B在接收M1时检测出了差错,就丢弃M1,其他什么都不做(也不会通知A收到有差错的分组)。又或者A传送的过程中分组丢失了,以上这两种情况下,B不会发送任何信息。
既然说它是可靠传输协议,那自然有它可靠的方法:如果发生以上的情况,A只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,所以它会重传刚刚的发送过的分组,也就是所谓的超时重传。
超时重传的原理也很简单:发送方发送完一个分组后,就会设置一个超时计时器,如果超时计时器到期之前没有收到接收方发来的确认信息,则会重发刚发送过的分组;如果收到确认信息,则撤销该超时计时器。如下图所示:
image.png
这里应该注意的是:
①既然发送方发送的分组可能丢失或者有差错,可能需要重传,那么它必须暂时保留已发送的分组副本,只有收到确认后,才清除这个副本。
②分组和确认分组信息都应该有各自的编号,用来标示每一个分组和确认信息。(这样才知道需要发送哪个分组,收到了哪个分组的确认信息)
③超时计时器设置的时间应该略长于分组传送往返时间。
image.png
3.确认丢失和确认延迟
没有正常进行通信,除了发送方出现问题外,接收方同时也可能存在问题。
例如,如果A发送了M1分组,到达B,B发送了M1确认信息,但由于网络原因,该确认信息丢失。那么这个时候,A在超时重传时间内,没有收到B的确认信息,而且它并不知道是自己的分组有差错、丢失,还是B发生的确认丢失了。因此,A会在超时重传过后,重传M1分组。
接收方B会采取这两个行动:
①B会丢弃M1分组,不向上层交付。(B之前已经收到过M1分组了)
②向A发送确认(因为A重发了,肯定重传时间内没有收到确认信息)
image.png
还有可能是另一种情况,就是B发送了确认,没有丢失,但是延迟了。也就是说,B发送的确认在A超时计时器过期后才到达。 这种情况下,A收到确认信息后会丢弃,然后重传刚才的分组,B收到后,丢弃重复的分组,并重传确认信息。
image.png
根据上述的确认和重传机制,我们就可以在不可靠的网络上实现可靠的传输。
4.信道利用率
停止等待ARQ协议的优点是简洁,但也有很严重的缺点,就是信道利用率太低。如下图所示:
image.png
信道利用率U = TD / (TD + RTT + TA)

连续ARQ协议

由于停止等待ARQ协议信道利用率太低,所以需要使用连续ARQ协议来进行改善。这个协议会连续发送一组数据包,然后再等待这些数据包的ACK。
发送方采用流水线传输。流水线传输就是发送方可以连续发送多个分组,不必每发完一个分组就停下来等待对方确认。如下图所示:
image.png
连续ARQ协议通常是结合滑动窗口协议来使用的,发送方需要维持一个发送窗口,如下图所示:
image.png
图(a)是发送方维持的发送窗口,它的意义是:位于发送窗口内的5个分组都可以连续发送出去,而不需要等待对方的确认,这样就提高了信道利用率。
连续ARQ协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。例如上面的图(b),当发送方收到第一个分组的确认,就把发送窗口向前移动一个分组的位置。如果原来已经发送了前5个分组,则现在可以发送窗口内的第6个分组。
接收方一般都是采用累积确认的方式。也就是说接收方不必对收到的分组逐个发送确认。而是在收到几个分组后,对按序到达的最后一个分组发送确认。如果收到了这个分组确认信息,则表示到这个分组为止的所有分组都已经正确接收到了。
累积确认的优点是容易实现,即使确认丢失也不必重传。但缺点是,不能正确的向发送方反映出接收方已经正确收到的所有分组的信息。比如发送方发送了前5个分组,而中间的第3个分组丢失了,这时候接收方只能对前2个发出确认。而不知道后面3个分组的下落,因此只能把后面的3个分组都重传一次,这种机制叫Go-back-N(回退N),表示需要再退回来重传已发送过的N个分组。

滑动窗口协议

滑动窗口协议在在发送方和接收方之间各自维持一个滑动窗口,发送发是发送窗口,接收方是接收窗口,而且这个窗口是随着时间变化可以向前滑动的。它允许发送方发送多个分组而不需等待确认。TCP的滑动窗口是以字节为单位的。
如下图所示,发送窗口中有四个概念::已发送并收到确认的数据(不在发送窗口和发送缓冲区之内)、已发送但未收到确认的数据(位于发送窗口之内)、允许发送但尚未发送的数据(位于发送窗口之内)、发送窗口之外的缓冲区内暂时不允许发送的数据。
接收窗口中也有四个概念:已发送确认并交付主机的数据(不在接收窗口和接收缓冲区之内)、未按序收到的数据(位于接收窗口之内)、允许的数据(位于接收窗口之内)、不允许接收的数据(位于发送窗口之内)。
image.png
规则:

  1. 凡是已经发送过的数据,在未收到确认之前,都必须暂时保留,以便在超时重传时使用。
  2. 只有当发送方A收到了接收方的确认报文段时,发送方窗口才可以向前滑动几个序号。
  3. 当发送方A发送的数据经过一段时间没有收到确认(由超时计时器控制),就要使用回退N步协议,回到最后接收到确认号的地方,重新发送这部分数据。

此外,TCP利用滑动窗口协议来进行流量控制,如下图所示:
image.png

TCP的listen、backlog

listen状态是服务器接收连接建立的必经之路。调用listen后,服务器即进入了LISTEN状态。

  1. int listen(int sockfd, int backlog);

backlog是一个建议值,用于指定内部的队列大小,以控制同时建立的连接请求数量。
在UNP中,这个值是这样描述的:
内核维护两个队列,一个是未完成队列,一个是已建立连接的队列,backlog是指这两个队列长度的总和。在第一个sync到达时,先将连接塞入第一个队列,再回复ACK+SYNC。此时,连接状态变为SYN_RCVD;
第二个是完成队列。客户端的ACK上来后,对应的连接移入完成队列。此状态的连接会被accept系统调用返回,状态变为ESTABLISHED。另一方面,如果请求上来时队列已满,则TCP忽略之。客户端来重试。

UDP协议

image-20200211194653599.png
与TCP协议的区别:


UDP TCP
是否连接 无连接 面向连接
是否可靠 不可靠传输 可靠传输,使用流量控制和拥塞控制
连接对象个数 支持一对一,一对多,多对一和多对多交互通信 只能是一对一通信
传输方式 面向报文 面向字节流
首部开销 首部开销小,仅8字节 首部最小20字节,最大60字节
适用场景 适用于实时应用(QQ、IP电话、视频会议、直播等) 适用于要求可靠传输的应用,例如文件传输

IP协议

IP协议为网络层协议,主要是在相互连接的网络之间传递IP数据报,主要功能有两方面,分别是寻址与路由和分段与重组,而在IP协议当中,最重要的就是TTL(IP允许通过的最大网段数量)字段(八位),规定该数据包能穿过几个路由之后才会被抛弃。IP报文如下所示:
image-20200229200430528.png

  • 4位版本号:表示IP协议的版本,IPV4的值0100,IPV6的值0110;
  • 4位首部长度:指的是IP包头部的长度,最大值是15,即 15 * 32 / 8 = 60个字节,所以选项部分的最大值是40个字节;
  • 8位服务类型:前3位表示优先级、后4位是标志位、最后一位保留未用;
  • 16位总长度:指的是IP包的总长度,最大长度是65535个字节。在以太网上允许的最长包长为1500B,所以当IP包过大时会进行分片传输;
  • 16位标识符:用于数据在分段传输时标识其序列号;(每从上层接收到一个数据报时,就将内置的一个累加器加1,并将其值赋值到标识符字段)
  • 3位标志:三位从左到右分别为MF、DF、未用。MF=0表示没有更多的分片;DF=1表示路由器不能对改数据包分段;(如果IP报文过大时,会存在同一个IP数据报文被分片的情况)
  • 13位片偏移:也称为段偏移,用于标识数据包在上层初始数据报文中的偏移量;(如果同一个IP数据包本分片后,通过片偏移就可以知道分片的相对位置)
  • 8位生存时间:初始值由操作系统设置,每经过一个路由器转发后其值都会建议,如果其值等于0后还没有到达目的地,就行丢弃该数据包;
  • 8位协议:标识上层所使用的协议;
  • 16位首部校验和:只对IP数据包的首部进行校验,不包含数据部分;
  • 32位源IP地址:标识数据从哪里来;
  • 32位目的IP:标识数据到哪里去;
  • 选项部分:主要有安全和处理限制、记录路径、时间戳等。

    以太网帧

    在数据链路层中,使用最多的就是以太网,而以太网帧因为历史原因存在多个版本,这里采用 IEEE 802.3 以太帧格式。
    image-20200229200751442.png

  • 前导码:7 个字节,用于数据传输过程中的双方发送与接收的速率的同步。

  • SFD:帧开始符,1 个字节,用于标识一个以太网帧的开始。
  • 目的 MAC 地址:6 个字节,指明帧的接收者。
  • 源 MAC 地址:6 个字节,指明帧的发送者。
  • 长度:2 个字节,指明该帧数据字段的长度,但不代表数据字段长度能够达到 2^16 字节。
  • 类型:2 个字节,指明帧中数据的协议类型,比如常见的 IPv4 中的 ip 协议采用 0x0800。
  • 数据与填充:46~1500 个字节,包含了上层协议传递下来的数据,如果加入数据字段后帧长度不够 64 字节,会在数据字段加入填充字段达到 64 字节。
  • 校验和:4 个字节,对接收网卡(主要是检测数据与填充字段)提供判断是否传输错误的一种方法,如果发现错误,则丢弃此帧。目前最为流行的用于校验和(FCS)的算法是循环冗余校验(cyclic redundancy check — CRC)。

    数据包的封装和解封过程

    image-20200229201207993.png

    三次握手

    image-20200211191040778.png
    第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

    四次挥手

    image-20200211191437556.png
  1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
  2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
  3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
  4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态
  6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

问题

  1. 为什么连接需要三次握手,而挥手需要四次?答:当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。
  2. 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?答:我们必须认为网络是不可靠的,最后一个ACK有可能会丢失,Server如果没有收到ACK,将不断重复发送FIN片段,所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
  3. 为什么不能两次握手?答:网络传输可能延迟,如果只使用两次握手,无法确保数据完整,有序,还会造成不必要的开销。
  4. 怎么查看time_wait连接数?以及怎么解决time_wait过多的现象?答:netstat -an |grep TIME_WAIT|wc -l 。在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。可以修改/etc/sysctl.conf文件,使TIME_WAIT重用和快速回收。
  5. 第三次握手失败会怎么样?不会重传ack,而是直接发送RTS报文段,进入CLOSED状态,这样做可以有效避免SYN洪泛攻击。所谓的洪泛攻击是指伪造IP对被攻击端进行请求,被攻击端的响应报文无法到达,使资源很快耗尽。

    HTTP1.0、HTTP1.1和HTTP2.0

    HTTP1.0和HTTP1.1

  • 长连接HTTP1.1开始支持长连接。Keep—Alive允许在一定时间内,同一个域名多次请求数据,只建立一次http连接,其他请求可以复用这个连接通道,以达到提高请求效率的目的。
  • 节约带宽HTTP1.1支持只发送header信息。
  • HOST域HTTP1.1必须要求传输HOST域。
  • 缓存处理HTTP1.1引入了更多的缓存控制策略。
  • 错误通知的管理在HTTP1.1中新增了24个错误状态响应码。
  • 新增管道机制如果浏览器要向一个域名发送多个请求,需要在本地维护一个FIFO队列,完成了一个再发送下一个,这样就存在一个问题,服务端从完成一个请求开始回传,到收到下一个请求的这段时间内是处于空闲状态的。而管道机制可以将浏览器的请求一次性全部发给服务器,服务器可以连续处理,就不存在空闲状态。存在的问题
    1. 如果第一个请求处理特别慢,将会造成阻塞,称之为队首阻塞。
    2. 服务端为了保证顺序回传,通常需要缓存多个响应,从而占用更多服务器资源,也更容易被攻击。
    3. 如果处理过程中网络异常,可能得全部重复处理。
    4. 一些中间代理设备不一定支持管道。

      HTTP1.1和HTTP2.0

      1、多路复用
      长连接是指对同一个文件(xx.css)的多次访问可以复用同一个tcp连接,而对于不同文件是没办法复用的,而2.0的多路复用是指同一个域名访问多个文件的请求也可以复用一个tcp连接,且多个请求可以被并行处理。并行实现的原理就是二进制帧的设计:
      http/2最大特点是使用二进制帧数据进行传输,几个概念如下:帧: http/2数据通信的最小单位。每个帧都包含帧首部,其中会标识当前帧所属的流。消息: 指http/2中逻辑上的http消息。例如请求和响应等,消息由一个或多个帧组成。 、流: 存在于连接中的虚拟通道。流可以承接双向消息,每个流都有一个唯一的整数id。连接: 与http/1相同,都是指对应的TCP连接。http/1的请求和响应报文,都是由起始行、首部和实体正文(可选)组成,各部分之间以文本换行符分隔。而http/2将请求和响应数据分隔成为更小的帧,并对他们采用二进制编码。http/2 中,同域名下的所有请求都在一个连接上完成,这个连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,消息由一个或多个帧组成。多个帧之间可以乱序发送,然后根据帧首部的流标识可以重新组装。
      也就是说2.0下,可以实现并行发送,顺序组装。
      2、头部数据压缩
      http请求都是由状态行、请求/响应头部、消息主体三部分组成,一般而言,消息主体都会经过gzip压缩,或者本身传输的就是压缩后的二进制文件(例如图片、音频),但是状态行和头部却没有经过任何压缩,直接以文本传输。对于一个请求而言,其headers所占的字节数也不少,尤其cookie,有些时候headers甚至超过了主体的大小。头部压缩使用了HPACK算法。会在支持http/2的浏览器和服务端之间:
  1. 维护一份相同的静态字典,包含常见的头部名称以及特别常见的头部名称和值的组合。这样对完全匹配的头部键值对,例如:method:GET,就可以使用一个字符表示。对于头部名称可以匹配的,例如cookie: xxx,可以将名称使用一个字符表示。
  2. 维护一份相同的动态字典,可以动态的添加内容。
  3. 支持基于静态哈夫曼码表的哈夫曼编码(Huffman Coding)

3、服务器推送
支持服务端推送,意味着服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置再发起请求。这样客户端可以直接从本地加载这些资源,不用再通过网络。

拥塞控制

当出现丢包事件时,让发送方降低其发送速率,步骤分别有慢启动->拥塞避免>快速恢复。

慢启动

TCP发送方初始阶段不是线性地增加其发送率,而是以指数的速度增加,即每过一个RTT(数据从网络一端传到另一端所需的时间)将cwnd(拥塞窗口)值翻倍
结束时机:

  1. 发生一个由超时指示的丢包事件(即拥塞),将ssthresh(阈值)状态变量设为cwnd值的一半,cwnd将设为1个MSS(最大传输大小),并重新开始慢启动。
  2. 当cwnd的值到达或超过ssthresh时,结束慢启动,TCP转移到拥塞避免模式。
  3. 若检测到3个冗余ACK,TCP执行快速重传,并进入快速恢复状态。

快速重传:
快重传算法要求首先接收方收到一个失序的报文段后就立刻发出重复确认,而不要等待自己发送数据时才进行捎带确认。

拥塞避免

当cwnd拥塞避免的主要思想是加法增大,也就是cwnd的值不再指数级往上升,开始加法增加。此时当窗口中所有的报文段都被确认时,cwnd的大小加1MSS,即TCP发送方每收到一个新的确认ACK,就将cwnd增加一个MSS/cwnd字节,cwnd的值就随着RTT开始线性增加,这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。
结束时机:

  1. 出现超时,ssthresh被设置为cwnd的一半,cwnd的值被置为1个MSS,进入慢启动。
  2. 收到3个冗余ACK,ssthresh被设置为cwnd的一半,cwnd为原来的一半加上3个MSS,进入快速恢复状态。

    快速恢复

  3. 当收到3个重复ACK时,把ssthresh设置为cwnd的一半,把cwnd设置为ssthresh的值加3,然后重传丢失的报文段,即ssthresh=cwnd/2,cwnd=ssthresh+3

  4. 收到重复的ACK时,cwnd增加1;
  5. 当收到新的数据包的ACK时,把cwnd设置为第一步中的ssthresh的值,再次进入拥塞避免状态;
  6. 出现超时,ssthresh被设置为cwnd的一半,cwnd设为1个MSS,进入慢启动状态。

最终呈现锯齿形状:
image-20200211202558767.png
image.png

HTTP状态码

1:信息,服务器收到请求,需要请求者继续执行操作。
2
:成功,操作被成功接收并处理。
3:重定向,需要进一步的操作以完成请求。
4
:客户端错误,请求包含语法错误或无法完成请求。
5**:服务器错误,服务器在处理请求的过程中发生了错误。

常见状态码

状态码 含义
100 客户端应重新发送初始请求,并在请求中附上第一次请求时未提供的(可能很大或者包含敏感信息的)表示。
200 表示从客户端发来的请求在服务器端被正确处理。
201 当服务器依照客户端的请求创建了一个新资源时,发发送此响应代码。
204 无内容,服务器成功处理了请求,但没有返回任何内容。
301 永久性重定向,表示资源已被分配了新的 URL。
302 临时性重定向,表示资源临时被分配了新的 URL。
303 查看其它位置,表示资源存在着另一个 URL,应使用 GET 方法定向获取资源。
304 未修改,自从上次请求后,请求的网页未修改过。
307 临时重定向,和302含义相同。
400 服务器不理解请求的语法。
401 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403 服务器拒绝请求。
404 未找到,服务器找不到请求的网页。
409 服务器在完成请求时发生冲突,服务器必须在响应中包含有关冲突的信息。
500 服务器遇到错误,无法完成请求。
502 服务器作为网关或代理,从上游服务器收到无效响应。
504 服务器作为网关或代理,但是没有及时从上游服务器收到请求。

Select、Poll、Epoll之间的区别

  1. select(O(n)时间复杂度)基于顺序扫描,select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理,需要无差别轮询所有的数据流,同时,只能监视fd的个数为32位1024个,64位2048个。
  2. poll(O(n)时间复杂度)本质和select没有区别,将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,但是没有最大连接数的限制。
  3. epoll(O(1)时间复杂度)基于事件驱动,流如果发生I/O事件会触发异步回调,可以将时间复杂度降为O(1),同时没有并发数量的限制。 |
    | select | poll | epoll | | —- | —- | —- | —- | | 操作方式 | 遍历 | 遍历 | 回调 | | 底层实现 | 数组 | 链表 | 哈希表 | | IO效率 | 每次调用都进行线性遍历,时间复杂度为O(n) | 每次调用都进行线性遍历,时间复杂度为O(n) | 事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪fd放到readyList里面,时间复杂度O(1) | | 最大连接数 | 1024(x86)或2048(x64) | 无上限 | 无上限 | | fd拷贝 | 每次调用select,都需要把fd集合从用户态拷贝到内核态 | 每次调用poll,都需要把fd集合从用户态拷贝到内核态 | 调用epoll_ctl时拷贝进内核并保存,之后每次epoll_wait不拷贝 |

TCP协议计时器

  • 超时重传计时器目的:避免无限等待确认报文。创建时间:在发送TCP报文段时,会为该报文段设置一个超时重传计时器。可能发生的情况:在超时时间到达之前,收到了该报文段的确认则撤销计时器,否则重传该报文段,并将超时重传计时器复位。重传时间:2*RTT(RTT为往返时间)。
  • 坚持计时器目的:解决零大小窗口导致的死锁问题。死锁产生原因:当接收端窗口大小为0时,发送端停止发送,此后如果接收端有空余空间来接收数据,则发送一个新窗口大小的报文,如果该报文丢失了则导致双方都处于等待状态,产生死锁。工作原理:当发送端接收到接收端发送的零大小窗口的报文时,就启动坚持计时器,当计时器到达计时时间,发送端就主动发送一个报文段告诉接收端你发送的新窗口大小的报文丢失了,需要重新发送。坚持时间 开始先设置为超时重传时间,如果超时了还是没有收到接收端发送的新窗口大小报文,则将计时器的值加倍并且复位,直到大于门限值60s,在此之后每隔60s向接收端发送一个询问报文。
  • 保活计时器目的:避免空闲连接长时间的占用服务器资源。工作原理:当服务器收到数据时都将保活计时器重新设置(一般2h),过了2h后,服务器如果没有收到数据,每隔75s发送一个探测报文给客户端,当连续发送10次后,仍然没有收到客户端的回复,则服务器断开连接。
  • 时间等待计时器(为服务器Time_Wait状态设置)服务器主动断开连接时,服务器会保持一个Time_wait状态,而时间等待计时器就是Time_wait状态的持续时间。

    RTO与RTT

    RTO (Retransmission Time Out):重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传。
    RTT (Round Trip Time):一个连接的往返时间,即数据发送时刻到接收到确认的时刻的差值。
    RTT和RTO 的关系是:由于网络波动的不确定性,每个RTT都是动态变化的,所以RTO也应随着RTT动态变化。

    HTTP和HTTPS的区别

    |
    | HTTP | HTTPS | | —- | —- | —- | | 是否需要CA | 不需要 | 需要,会产生一定的费用 | | 是否加密 | 明文传输 | SSL加密 | | 端口 | 80 | 443 | | 是否有状态 | 无状态 | 有状态 |

SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层:SSL记录协议(SSL Record Protocol),它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。SSL握手协议(SSL Handshake Protocol),它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

HTTPS建立连接的过程

image-20200211212636712.png

  • 客户端发出请求首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。
  • 服务器回应服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。
  • 客户端回应客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。
  • 服务器的最后回应服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的”会话密钥”。然后,向客户端最后发送下面信息。
    • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
    • 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用”会话密钥”加密内容。

HTTPS中间人攻击/为什么需要CA认证机构颁发证书?

中间人攻击的过程如下:

  1. 客户端请求被劫持,将所有的请求发送到中间人的服务器;
  2. 中间人服务器返回自己的证书;
  3. 客户端创建随机数,使用中间人证书中的公钥进行加密发送给中间人服务器,中间人使用私钥对随机数解密并构造对称加密,对之后传输的内容进行加密传输;
  4. 中间人通过客户端的随机数对客户端的数据进行解密;
  5. 中间人与服务端建立合法的https连接(https握手过程),与服务端之间使用对称加密进行数据传输,拿到服务端的响应数据,并通过与服务端建立的对称加密的秘钥进行解密;
  6. 中间人再通过与客户端建立的对称加密对响应数据进行加密后传输给客户端;
  7. 客户端通过与中间人建立的对称加密的秘钥对数据进行解密。

简单来说,中间人攻击中,中间人首先伪装成服务端和客户端通信,然后又伪装成客户端和服务端进行通信(如图)。 整个过程中,由于缺少了证书的验证过程,虽然使用了https,但是传输的数据已经被监听,客户端却无法得知。
image-20200229215736657.png

如何验证证书的合法性?

CA证书中会包含颁发机构信息、公钥、公司信息、域名、有效期等信息,浏览器验证证书:

  1. 首先就是要验证域名、有效期等信息是否正确;
  2. 然后判断证书来源的合法性。每份签发证书都可以根据验证链查找到对应的根证书,操作系统、浏览器会在本地存储权威机构的根证书,利用本地根证书可以对对应机构签发证书完成来源验证;
  3. 判断证书是否被篡改。需要与 CA 服务器进行校验;
  4. 判断证书是否已吊销。

以上任意一步都满足的情况下浏览器才认为证书是合法的。
image.png

在浏览器的URL中输入一个HTTPS请求会发生什么?

  • 判断输入的是一个合法的url还是一个待搜索的关键词,并且根据你输入的内容进行自动完成、字符编码等操作。
  • 首先进行域名解析,域名解析具体过程讲一下:
    1. 浏览器搜索自己的DNS缓存,缓存中维护一张域名与IP地址的对应表;
    2. 若没有,则搜索操作系统的DNS缓存;
    3. 若没有,则操作系统将域名发送至本地域名服务器(递归查询方式),本地域名服务器查询自己的DNS缓存,查找成功则返回结果,否则,通过以下方式迭代查找:
    4. 本地域名服务器向根域名服务器发起请求,根域名服务器返回com域的顶级域名服务器的地址;
    5. 本地域名服务器向com域的顶级域名服务器发起请求,返回权限域名服务器地址;
    6. 本地域名服务器向权限域名服务器发起请求,得到IP地址。
    7. 本地域名服务器将得到的IP地址返回给操作系统,同时自己将IP地址缓存起来;操作系统将IP地址返回给浏览器,同时自己也将IP地址缓存起来;至此,浏览器已经得到了域名对应的IP地址。
  • 浏览器发起HTTP请求;
  • 接下来到了传输层,选择传输协议,TCP或者UDP,TCP是可靠的传输控制协议,对HTTP请求进行封装,加入了端口号等信息;
  • 然后到了网络层,通过IP协议将IP地址封装为IP数据报;然后此时会用到ARP协议,主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址,找到目的MAC地址;
  • 接下来到了数据链路层,把网络层交下来的IP数据报添加首部和尾部,封装为MAC帧,现在根据目的mac开始建立TCP连接,三次握手(详细讲)。
  • 建立了TCP连接后,如果使用HTTPS,则需要进行SSL握手,沟通加密参数(如,SSL版本)以及交换秘钥,握手完成后,报文会在发送给TCP之前在SSL层进行加密。
  • 建立了TCP连接便可以发送HTTP请求了,HTTP请求通过TCP协议发到Server端,协议头讲一讲;
  • 一般大型的网站会将请求发送到反向代理服务中,因为当网站访问量非常大,网站越来越慢,一台服务器已经不够用了,于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台及其处理;
  • 接收端在收到物理层上交的比特流后,根据首尾的标记,识别帧的开始和结束,将中间的数据部分上交给网络层,然后层层向上传递到应用层;
  • 服务器响应请求并请求客户端要的资源,传回给客户端,返回响应内容讲一讲(状态行、响应头、响应正文);
  • 浏览器收到来自服务器的响应资源后,如果响应资源进行了压缩,还要进行解压;
  • 对响应资源做缓存,并对资源做解析:1.HTML通过HTML解析器解析输出DOM树,2.CSS样式通过样式解析器输出CSS规则,3.结合DOM树和CSS规则,计算出DOM树中每个结点的具体样式,生成渲染树,4.浏览器根据渲染树开始布局和绘制,会出发回流和重绘,5.构建图层数,显示页面。

    TCP与HTTP的关系,基于TCP实现HTTP

    TCP是传输层的协议,HTTP是应用层的协议,HTTP协议基于TCP通信。
    实现思路如下:
  1. http协议是基于TCP通信的协议,因此,实现web服务器的第一步至少要能实现两个主机不同进程之间的TCP通信。
  2. 接下来的部分就是比较主要的处理逻辑了,当服务器收到请求后,首先应该分析请求方法。(因为web服务器是要支持cgi的,但请求方法不同处理cgi也不同,这里我们只处理GET和POST方法)
  3. 当方法确定后,应该拿到请求的URL,这一步是为了我们后边能处理GET和POST方法的cgi。(GET和POST的参数位置不同,GET的参数在URL中,POST的参数在请求正文中)
  4. 判断资源是否存在,如果存在,判断这个资源是一个目录、普通文件还是一个可执行程序。之前几步我们已经提取到URL以及参数。GET方法:如果没有参数,就直接将请求的资源返回(即进入非cgi模式运行);否则,进入cgi模式内部运行;只要是POST方法就需要支持cgi:直接进入cgi函数内部运行。非cgi模式: 进入非cgi模式时一定是GET方法且没有参数,此时进入echo_www()函数内部即可,该函数会将所请求的资源以html的格式返回给浏览器。

    cgi模式

    首先服务器要从浏览器上读取参数,然后需要fork出一个子进程进行cgi部分的处理,父进程通过环境变量的方式将参数转交给子进程,子进程运行完成后,将结果交给父进程,父进程再将数据输出给浏览器。在这个过程中可以将父进程看作一个所谓的中间量,只进行了参数的转交,因此可以将子进程的输入输出文件描述符进行重定向,即子进程直接与浏览器“联系”。
    image-20200308153027902.png

    路由器和交换机的区别

    交换机比路由器更简单,路由器比交换器能获取更多信息。
  • 工作层次不同交换机工作在数据链路层;路由器工作在网络层。
  • 数据转发所依据的对象不同交换机的数据转发依据是利用物理地址或者说MAC地址来确定转发数据的目的地址;路由器是依据ip地址进行工作的。
  • 分割域不同传统的交换机只能分割冲突域,不能分割广播域;路由器可以分割广播域。

    重定向和转发的区别

    |
    | forward | redirect | | —- | —- | —- | | 地址栏 | 地址不变。服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器 | 地址发生改变。服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址 | | 数据共享 | 转发页面和转发到的页面可以共享request里面的数据 | 不可以共享 | | 运用场景 | 一般用于用户登陆的时候,根据角色转发到相应的模块 | 一般用于用户注销登陆时返回主页面和跳转到其它的网站等 | | 效率 | 高 | 低 |

cookie和session的区别


cookie session
存放位置 浏览器 服务器
安全性 不安全 安全
性能 对服务器压力小 当访问增多时,服务器压力大
数据大小 有大小限制,不能超过4K,很多浏览器最多保存20个cookie 没有大小限制

BS与CS的区别


BS CS
客户端 只需要浏览器 需要安装专门的软件
硬件 建立在广域网 建立在专用网络
安全要求 相对弱 对安全信息控制能力强
程序架构 更注重安全和访问速度 更注重流程
重用性
维护性 轻松 较困难
开发难度