首页 🍋Code,🥭笔记

计算机与网络

一、网络体系结构

å��ç��ä½�ç³"ç"�æ�� VS OS VS TCP/IP

推荐的连接:

七层架构主要包括:

  1. 物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由 1、0 转化为电流强弱来进行传输,到达目的地后在转化为 1、0,也就是我们常说的模数转换与数模转换)。这一层的数据叫做比特。
  2. 数据链路层:主要将从物理层接收的数据进行 MAC 地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
  3. 网络层:主要将从下层接收到的数据进行 IP 地址(例 192.168.0.1)的封装与解封装。在这一层工 作的设备是路由器,常把这一层的数据叫做数据包。
  4. 传输层:定义了一些传输数据的协议和端口号(WWW 端口 80 等),

如:TCP(传输控制协议, 传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议, 与 TCP 特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如 QQ 聊天数据就是通过这 种方式传输的)。 主要是将从下层接收的数据进行分段进行传输,到达目的地址后在进行重组。 常常把这一层数据叫做段。

  1. 会话层:==通过传输层(端口号:传输端口与接收端口)建立数据传输的通路==。主要在你的系统之间 发起会话或或者接受会话请求(设备之间需要互相认识可以是 IP 也可以是 MAC 或者是主机名)
  2. 表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等))
  3. 应用层:主要是一些终端的应用,比如说 FTP(各种文件下载),WEB(IE 浏览),QQ 之类的(你 就把它理解成我们在电脑屏幕上可以看到的东西.就 是终端应用)。

各层使用的数据交换设备:

  • 网关:应用层、传输层。

网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。

网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连。

  • 【重点】路由器:网络层

路由选择、存储转发

  • 【重点】交换机:数据链路层、网络层

识别数据包中的 MAC 地址信息,根据 MAC 地址进行转发,并将这些 MAC 地址与对应的端口记录在自己内部的一个地址表中。

  • 网桥:数据链路层

将两个 LAN 连起来,根据 MAC 地址来转发帧。

  • 集线器(Hub):物理层

纯硬件设备,主要用来连接计算机等网络终端。

  • 中继器:物理层

在比特级别对网络信号进行再生和重定时,从而使得它们能够在网络上传输更长的距离。

二、IP

IP 地址的分类

IP 地址是指互联网协议地址,是 IP 协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。

IP 地址编址方案将IP地址空间划分为 A、B、C、D、E 五类,其中 A、B、C 是基本类,D、E 类作为多播和保留使用,为特殊地址。

每个 IP 地址包括两个标识码(ID),即网络 ID 和主机 ID 。同一个物理网络上的所有主机都使用同一个网络 ID ,网络上的一个主机(包括网络上工作站,服务器和路由器等)有一个主机 ID 与其对应。A~E 类地址的特点如下:

五类互联网地址

  • A 类地址:以 0 开头,第一个字节范围:0~127 。
  • B 类地址:以 10 开头,第一个字节范围:128~191 。
  • C 类地址:以 110 开头,第一个字节范围:192~223。
  • D 类地址:以 1110 开头,第一个字节范围:224~239 。
  • E 类地址:以 1111 开头,保留地址。

详细的,可以看看 《IP 地址分类(A类 B类 C类 D类 E类)》 文章。

IP 地址与物理地址的区别

  • 物理地址(MAC 地址),是数据链路层和物理层使用的地址。
  • IP 地址是网络层和以上各层使用的地址,是一种逻辑地址。
  • 其中 ARP 协议用于 IP 地址与物理地址的对应。

详细的,可以看看 《即生瑜,何生亮 —— MAC 地址与 IP 地址》 文章。

网络层的 ARP 协议工作原理

网络层的 ARP 协议完成了 IP 地址与物理地址的映射。

  • 首先,每台主机都会在自己的 ARP 缓冲区中建立一个 ARP 列表,以表示 IP 地址和 MAC 地址的对应关系。
  • 当源主机需要将一个数据包要发送到目的主机时,会首先检查自己 ARP 列表中是否存在该 IP 地址对应的 MAC 地址:

    • 如果有,就直接将数据包发送到这个 MAC 地址。
    • 如果没有,就向本地网段发起一个ARP请求的广播包,查询此目的主机对应的 MAC 地址。此 ARP 请求数据包里包括源主机的 IP 地址、硬件地址、以及目的主机的 IP 地址。网络中所有的主机收到这个 ARP 请求后,会检查数据包中的目的 IP 是否和自己的 I P地址一致。

      • 如果不相同,就忽略此数据包。
      • 如果相同,该主机首先将发送端的 MAC 地址和 IP 地址添加到自己的 ARP 列表中(如果 ARP 表中已经存在该 IP 的信息,则将其覆盖),然后给源主机发送一个 ARP 响应数据包,告诉对方自己是它需要查找的 MAC 地址。

        • 源主机收到这个 ARP 响应数据包后,将得到的目的主机的 IP 地址和 MAC 地址添加到自己的 ARP 列表中,并利用此信息开始数据的传输。
        • 如果源主机一直没有收到 ARP 响应数据包,表示 ARP 查询失败。

注意,在 OSI 模型中 ARP 协议属于链路层;而在 TCP/IP 模型中,ARP 协议属于网络层。

三、TCP

TCP(Transmission Control Protocol),传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。主要特点如下:

  • TCP 是面向连接的。

就好像打电话一样,通话前需要先拨号建立连接,通话结束后要挂机释放连接

  • 每一条 TCP 连接只能有两个端点,每一条TCP连接只能是点对点的(一对一)。
  • TCP 提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。
  • TCP 提供全双工通信。TCP 允许通信双方的应用进程在任何时候都能发送数据。TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双方通信的数据。
  • ==面向字节流。==

TCP 中的“流”(Stream),指的是流入进程或从进程流出的字节序列。

“面向字节流”的含义是:虽然应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。

数据包说明

  1. 源端口号( 16 位):它(连同源主机 IP 地址)标识源主机的一个应用进程。
  2. 目的端口号( 16 位):==它(连同目的主机 IP 地址)标识目的主机的一个应用进程。这两个值加上 IP 报头中的源主机 IP 地址和目的主机 IP 地址唯一确定一个 TCP 连接。==
  3. 顺序号 seq( 32 位):用来标识从 TCP 源端向 TCP 目的端发送的数据字节流,它表示在这个报文段中的第一个数据字节的顺序号。如果将字节流看作在两个应用程序间的单向流动,则 TCP 用顺序号对每个字节进行计数。序号是 32bit 的无符号数,序号到达 2 的 32 次方 - 1 后 又从 0 开始。当建立一个新的连接时, SYN 标志变 1 ,顺序号字段包含由这个主机选择的该 连接的初始顺序号 ISN ( Initial Sequence Number )。
  4. 确认号 ack( 32 位):包含发送确认的一端所期望收到的下一个顺序号。因此,确认序号应当是上次已成功收到数据字节顺序号加 1 。==只有 ACK 标志为 1 时确认序号字段才有效。== TCP 为 应用层提供全双工服务,这意味数据能在两个方向上独立地进行传输。因此,连接的每一端必 须保持每个方向上的传输数据顺序号。
  5. TCP 报头长度( 4 位):给出报头中 32bit 字的数目,它实际上指明数据从哪里开始。需要这 个值是因为任选字段的长度是可变的。这个字段占 4bit ,因此 TCP 最多有 60 字节的首部。然 而,没有任选字段,正常的长度是 20 字节。
  6. 保留位( 6 位):保留给将来使用,目前必须置为 0 。
  7. 控制位( control flags , 6 位):在 TCP 报头中有 6 个标志比特,它们中的多个可同时被设置为 1 。依次为:
  8. URG :为 1 表示紧急指针有效,为 0 则忽略紧急指针值。
  9. ACK :为 1 表示确认号有效,为 0 表示报文中不包含确认信息,忽略确认号字段。
  10. PSH :为 1 表示是带有 PUSH 标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。
  11. RST :用于复位由于主机崩溃或其他原因而出现错误的连接。它还可以用于拒绝非法的报文段和拒绝连接请求。一般情况下,如果收到一个 RST 为 1 的报文,那么一定发生了某些问题。
  12. SYN :同步序号,为 1 表示连接请求,用于建立连接和使顺序号同步( synchronize )。
  13. FIN :用于释放连接,为 1 表示发送方已经没有数据发送了,即关闭本方数据流。
  14. 窗口大小( 16 位):数据字节数,表示从确认号开始,本报文的源方可以接收的字节数,即源 方接收窗口大小。窗口大小是一个 16bit 字段,因而窗口大小最大为 65535 字节。
  15. 校验和( 16 位):此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字 进行计算所得。这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证。
  16. 紧急指针(16位):只有当URG标志置1时紧急指针才有效。TCP的紧急方式是发送端向另 一端发送紧急数据的一种方式。
  17. 选项:最常见的可选字段是最长报文大小,又称为MSS(MaximumSegmentSize)。每个连 接方通常都在通信的第一个报文段(为建立连接而设置 SYN 标志的那个段)中指明这个选项, 它指明本端所能接收的最大长度的报文段。选项长度不一定是 32 位字的整数倍,所以要加填充 位,使得报头长度成为整字数。
  18. 数据: TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报 文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数 据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

image-20190417210917484

TCP 对应的应用层协议

  • FTP :定义了文件传输协议,使用 21 端口。常说某某计算机开了 FTP 服务便是启动了文件传输服务。下载文件,上传主页,都要用到 FTP 服务。
  • Telnet :它是一种用于远程登陆的端口,用户可以以自己的身份远程连接到计算机上,通过这种端口可以提供一种基于 DOS 模式下的通信服务。如以前的 BBS 是纯字符界面的,支持 BBS 的服务器将 23 端口打开,对外提供服务。
  • 邮箱

    • SMTP :定义了简单邮件传送协议,现在很多邮件服务器都用的是这个协议,用于发送邮件。如常见的免费邮件服务中用的就是这个邮件服务端口,所以在电子邮件设置-中常看到有这么 SMTP 端口设置这个栏,服务器开放的是 25 号端口。
    • POP3 :它是和 SMTP 对应,POP3 用于接收邮件。通常情况下,POP3 协议所用的是 110 端口。也是说,只要你有相应的使用 POP3 协议的程序(例如 Foxmail 或 Outlook),就可以不以 Web 方式登陆进邮箱界面,直接用邮件程序就可以收到邮件(如是 163 邮箱就没有必要先进入网易网站,再进入自己的邮箱来收信)。
  • HTTP :从 Web 服务器传输超文本到本地浏览器的传送协议。

TCP 头部

【重要】TCP 三次握手

三次握手,简单来说,就是:

TCP 三次握手的漫画

  • 发送方:我要和你建立链接?
  • 接收方:你真的要和我建立链接么?
  • 发送方:我真的要和你建立链接,成功。

详细来说,步骤如下:

TCP 三次握手的干货

ACK :为 1 表示确认号有效,为 0 表示报文中不包含确认信息,忽略确认号字段。

SYN :同步序号,为 1 表示连接请求,用于建立连接和使顺序号同步( synchronize )。

顺序号 seq( 32 位):用来标识从 TCP 源端向 TCP 目的端发送的数据字节流,它表示在这个报文段中的第一个数据字节的顺序号。如果将字节流看作在两个应用程序间的单向流动,则 TCP 用顺序号对每个字节进行计数。序号是 32bit 的无符号数,序号到达 2 的 32 次方 - 1 后 又从 0 开始。当建立一个新的连接时, SYN 标志变 1 ,顺序号字段包含由这个主机选择的该 连接的初始顺序号 ISN ( Initial Sequence Number )。

确认号 ack( 32 位):包含发送确认的一端所期望收到的下一个顺序号。因此,确认序号应当是上次已成功收到数据字节顺序号加 1 。只有 ACK 标志为 1 时确认序号字段才有效。 TCP 为 应用层提供全双工服务,这意味数据能在两个方向上独立地进行传输。因此,连接的每一端必 须保持每个方向上的传输数据顺序号。

  • 第一次握手:Client 将标志位 SYN=1 ,随机产生一个值 seq=J ,并将该数据包发送给 Server 。此时,Client 进入SYN_SENT 状态,等待 Server 确认。
  • 第二次握手:Server 收到数据包后由标志位 SYN=1 知道Client请求建立连接,Server 将标志位 SYNACK 都置为 1 ,ack=J+1,随机产生一个值 seq=K ,并将该数据包发送给 Client 以确认连接请求,Server 进入 SYN_RCVD 状态。此时,Server 进入 SYC_RCVD 状态。
  • 第三次握手:Client 收到确认后,检查ack是否为J+1,ACK是否为 1 。

    • 如果正确,则将标志位 ACK 置为 1 ,ack=K+1 ,并将该数据包发送给 Server 。此时,Client 进入 ESTABLISHED 状态。
    • Server 检查 ack 是否为 K+1ACK 是否为 1 ,如果正确则连接建立成功。此时 Server 进入 ESTABLISHED 状态,完成三次握手,随后 Client 与 Server 之间可以开始传输数据了。
  • 仔细看来,Client 会发起两次数据包,分别是 SYNCACK ;Server 会发起一次数据包,包含 SYNCACK 。也就是说,三次握手的过程中,Client 和 Server 互相做了一次 SYNCACK

三次握手的原因

第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。

客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。

为什么 TCP 连接需要三次握手

为了防止已失效的连接请求报文突然又传送到了服务端,因而产生错误。

客户端发出的连接请求报文并未丢失,而是在某个网络节点长时间滞留了,以致延误到链接释放以后的某个时间才到达 Server 。

  • 若不采用“三次握手”,那么只要 Server 发出确认数据包,新的连接就建立了。由于 Client 此时并未发出建立连接的请求,所以其不会理睬 Server 的确认,也不与 Server 通信;而这时 Server 一直在等待 Client 的请求,这样 Server 就白白浪费了一定的资源。
  • 若采用“三次握手”,在这种情况下,由于 Server 端没有收到来自客户端的确认,则就会知道 Client 并没有要求建立请求,就不会建立连接。

《通俗大白话来理解 TCP 协议的三次握手和四次挥手》 中,搜 “为什么要三次握手” 关键字,也有非常好的解答。

  • 这就很明白了,防止了服务器端的一直等待而浪费资源

【重要】什么是 TCP 四次挥手

四次挥手,简单来说,就是:

  • 发送方:我要和你断开连接!
  • 接收方:好的,断吧。
  • 接收方:我也要和你断开连接!
  • 发送方:好的,断吧。

详细来说,步骤如下:

image-20190418100353946

如下使用 Client 和 Server 的方式,仅仅是为了方便,也是可以从 Server 向 Client 发起。

  • 第一次挥手:Client 发送一个 FIN=M ,用来关闭 Client 到 Server 的数据传送。此时,Client 进入FIN_WAIT_1 状态。
  • 第二次挥手,Server 收到 FIN 后,发送一个 ACK 给 Client ,确认序号ack为 M+1(与 SYN 相同,一个 FIN 占用一个序号)。此时,Server 进入 CLOSE_WAIT 状态。==注意,TCP 链接处于半关闭状态,即客户端已经没有要发送的数据了,但服务端若发送数据,则客户端仍要接收。==
  • 第三次挥手,Server 发送一个 FIN=N ,用来关闭 Server 到 Client 的数据传送。此时 Server 进入 LAST_ACK 状态。
  • 第四次挥手,Client 收到 FIN 后,此时 Client 进入 TIME_WAIT 状态(此时 TCP 连接还没有释放掉,然后经过时间等待计时器设置的 2MSL 后,A 才进入到close 状态)。接着,Client 发送一个 ACK 给 Server ,确认序号为 N+1 。Server 接收到后,此时 Server 进入 CLOSED 状态,完成四次挥手。

去向ACK消息最大存活时间(MSL) + 来向FIN消息的最大存活时间(MSL)。恰恰就是2MSL( Maximum Segment Life)。

等待2MSL时间,客户端就可以放心地释放TCP占用的资源、端口号,此时可以使用该端口号连接任何服务器。

为什么要四次挥手?

TCP 协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP 是全双工模式,这就意味着:

  • 当主机 1 发出 FIN 报文段时,只是表示主机 1 已经没有数据要发送了,主机 1 告诉主机 2 ,它的数据已经全部发送完毕了;但是,这个时候主机 1 还是可以接受来自主机 2 的数据;==当主机 2 返回 ACK 报文段时,表示它已经知道主机 1 没有数据发送了,但是主机 2 还是可以发送数据到主机 1 的。==
  • 当主机 2 也发送了 FIN 报文段时,这个时候就表示主机 2 也没有数据要发送了,就会告诉主机 1 ,我也没有数据要发送了,之后彼此就会愉快的中断这次 TCP 连接。

TCP 建立连接要进行三次握手,而断开连接要进行四次。这是由于 TCP 的半关闭造成的。因为 TCP 连接是全双工的(即数据可在两个方向上同时传递)所以进行关闭时每个方向上都要单独进行关闭。这个单方向的关闭就叫半关闭。当一方完成它的数据发送任务,就发送一个 FIN 来向另一方通告将要终止这个方向的连接。

如果要正确的理解四次的原理,就需要了解四次挥手过程中的状态变化。

主动方=发送方;被动方=接收方。

状态前面的(主动方)(被动方),表示该状态属于谁。

  • (主动方)FIN_WAIT_1 :其实 FIN_WAIT_1 和 FIN_WAIT_2 状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:

    • FIN_WAIT_1 状态实际上是当 Socket 在 ESTABLISHED 状态时,它想主动关闭连接,向对方发送了 FIN 报文,此时该 Socket 即进入到 FIN_WAIT_1 状态。
    • 当对方回应 ACK 报文后,则进入到 FIN_WAIT_2 状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK 报文。所以, FIN_WAIT_1 状态一般是比较难见到的,而 FIN_WAIT_2 状态还有时常常可以用 netstat 看到。
  • (主动方)FIN_WAIT_2 :上面已经详细解释了这种状态,实际上 FIN_WAIT_2 状态下的 Socket,表示半连接,也即有一方要求 close 连接,但另外还告诉对方,我暂时还有点数据需要传送给你(ACK 信息),稍后再关闭连接。
  • (被动方)CLOSE_WAIT :这种状态的含义其实是表示在等待关闭。即当对方 close 一个 Socket 后发送 FIN 报文给自己,你系统毫无疑问地会回应一个 ACK 报文给对方,此时则进入到 CLOSE_WAIT 状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close 这个 Socket ,发送 FIN 报文给对方,也即关闭连接。所以你在 CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。
  • (被动方)LAST_ACK :这个状态还是比较容易好理解的,它是被动关闭一方在发送 FIN 报文后,最后等待对方的 ACK 报文。当收到 ACK 报文后,也即可以进入到 CLOSED 可用状态了。
  • (主动方)TIME_WAIT :表示收到了对方的 FIN 报文,并发送出了 ACK 报文,就等 2MSL 后即可回到 CLOSED 可用状态了。如果 FIN_WAIT_1 状态下,收到了对方同时带 FIN 标志和 ACK 标志的报文时,可以直接进入到 TIME_WAIT 状态,而无须经过 FIN_WAIT_2 状态。

为何一定要等 2MSL ?

如果不等,释放的端口可能会重连刚断开的服务器端口,这样依然存活在网络里的老的 TCP 报文可能与新 TCP 连接报文冲突,造成数据冲突,为避免此种情况,需要耐心等待网络老的 TCP 连接的活跃报文全部死翘翘,2MSL 时间可以满足这个需求(尽管非常保守)!

更多,可以看看知乎 《为什么 TCP 4 次挥手时等待为 2MSL?》 的讨论。

  • CLOSED :表示连接中断。

另外,关于 TIME_WAIT 和 CLOSE_WAIT 状态的区别《TIME_WAIT 和 CLOSE_WAIT 状态区别》

【重要】TCP 数据如何传输?

建立连接后,两台主机就可以相互传输数据了。如下图所示:TCP 套接字的数据交换过程

  • 上图给出了主机 A 分 2 次(分 2 个数据包)向主机 B 传递 200 字节的过程。
  • 首先,主机 A 通过 1 个数据包发送 100 个字节的数据,数据包的Seq号设置为 1200 。主机 B 为了确认这一点,向主机 A 发送ACK包,并将Ack号设置为 1301 。

    • 为了保证数据准确到达,目标机器在收到数据包(包括 SYN 包、FIN 包、普通数据包等)包后必须立即回传ACK包,这样发送方才能确认数据传输成功。
    • 此时Ack号为 1301 而不是 1201,==原因在于Ack号的增量为传输的数据字节数。假设每次Ack号不加传输的字节数,这样虽然可以确认数据包的传输,但无法明确 100 字节全部正确传递还是丢失了一部分,比如只传递了 80 字节。因此按如下的公式确认Ack号:Ack =Seq号 + 传递的字节数 + 1 。==

      • 与三次握手协议相同,最后加 1 是为了告诉对方要传递的 Seq 号。

OK,让我们重新来看下 TCP 的整个过程。如下图所示:img

TCP 数据传输丢失怎么办(TCP重传,通过定时器实现)

也可以改成提问,什么是 TCP 重传。

因为各种原因,TCP 数据包可能存在丢失的情况,TCP 会进行数据重传。如下图所示:

TCP套接字数据传输过程中发生错误

  • 上图表示通过 Seq 1301 数据包向主机 B 传递 100 字节的数据,但中间发生了错误,主机 B 未收到。经过一段时间后,主机 A 仍未收到对于 Seq 1301 的 ACK 确认,因此尝试重传数据。==为了完成数据包的重传,TCP 套接字每次发送数据包时都会启动定时器,如果在一定时间内没有收到目标机器传回的 ACK 包,那么定时器超时,数据包会重传。==上图演示的是数据包丢失的情况,也会有 ACK 包丢失的情况,一样会重传。
  • 重传超时时间(RTO,Retransmission Time Out)

这个值太大了会导致不必要的等待,太小会导致不必要的重传,理论上最好是网络 RTT 时间,但又受制于网络距离与瞬态时延变化,所以实际上使用自适应的动态算法(例如 Jacobson 算法和 Karn 算法等)来确定超时时间。

==往返时间(RTT,Round-Trip Time)表示从发送端发送数据开始,到发送端收到来自接收端的 ACK 确认包(接收端收到数据后便立即确认),总共经历的时延。==

  • 重传次数

TCP 数据包重传次数,根据系统设置的不同而有所区别。有些系统,一个数据包只会被重传 3 次,如果重传 3 次后还未收到该数据包的 ACK 确认,就不再尝试重传。但有些要求很高的业务系统,会不断地重传丢失的数据包,以尽最大可能保证业务数据的正常交互。

最后需要说明的是,==发送端只有在收到对方的 ACK 确认包后,才会清空输出缓冲区中的数据==。

ps:TCP 数据传输的过程,和 MQ Broker 投递消息给 Consumer 是一样的,只有在 Consumer Ack 确认消息已经消费,该消息才不会再被投递给 Consumer 。

另外,也推荐阅读 《网络基本功(九):细说TCP重传》

【重要】TCP 滑动窗口

在看 TCP 滑动窗口的概念之前,我们先来看看它出现的背景

将 TCP 与 UDP 这样的简单传输协议区分开来的是,它传输数据的质量。TCP 对于发送数据进行跟踪,这种数据管理需要协议有以下两大关键功能:

  • 可靠性:保证数据确实到达目的地。如果未到达,能够发现并重传。
  • 数据流控:管理数据的发送速率,以使接收设备不致于过载。

要完成这些任务,整个协议操作是围绕==滑动窗口 + 确认机制==来进行的。因此,理解了滑动窗口,也就是理解了 TCP 。

那么,到底什么是 TCP 滑动窗口呢?

滑动窗口协议,是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。

TCP 的滑动窗口解决了端到端的流量控制问题,允许接受方对传输进行限制,直到它拥有足够的缓冲空间来容纳更多的数据。

==TCP将独立的字节数据当作流来处理。一次发送一个字节并接收一次确认显然是不可行的。即使重叠传输(即不等待确认就发送下一个数据),速度也还是会非常缓慢。==

image002.jpg

TCP消息确认机制如上图所示,首先,每一条消息都有一个识别编号,每一条消息都能够被独立地确认,因此同一时刻可以发送多条信息。设备B定期发送给A一条发送限制参数,制约设备A一次能发送的消息最大数量。设备B可以对该参数进行调整,以控制设备A的数据流。

为了提高速度,TCP并没有按照字节单个发送而是将数据流划分为片段。片段内所有字节都是一起发送和接收的,因此也是一起确认的。确认机制没有采用message ID字段,而是使用的片段内最后一个字节的sequence number。因此一次可以处理不同的字节数,这一数量即为片段内的sequence number。

==TCP数据流的概念划分类别==

假设A和B之间新建立了一条TCP连接。设备A需要传送一长串数据流,但设备B无法一次全部接收,所以它限制设备A每次发送分段指定数量的字节数,直到分段中已发送的字节数得到确认。之后,设备A可以继续发送更多字节。每一个设备都对发送,接收及确认数据进行追踪。

如果我们在任一时间点对于这一过程做一个“快照”,那么我们可以将TCP buffer中的数据分为以下四类,并把它们看作一个时间轴:

1. 已发送已确认 数据流中最早的字节已经发送并得到确认。这些数据是站在发送设备的角度来看的。如下图所示,31个字节已经发送并确认。

2. 已发送但尚未确认 已发送但尚未得到确认的字节。发送方在确认之前,不认为这些数据已经被处理。下图所示14字节为第2类。

3. 未发送而接收方已Ready 设备尚未将数据发出,但接收方根据最近一次关于发送方一次要发送多少字节确认自己有足够空间。发送方会立即尝试发送。如图,第3类有6字节。

4. 未发送而接收方Not Ready 由于接收方not ready,还不允许将这部分数据发出。

image-20190418115538022

接收方采用类似的机制来区分已接收并已确认,尚未接受但准备好接收,以及尚未接收并尚未准备好接收的数据。实际上,收发双方各自维护一套独立的变量,来监控发送和接收的数据流落在哪一类。

滑动窗口的原理

TCP是一个可靠的传输协议,所以需要对数据进行确认。TCP协议里窗口机制有2种:一种是固定的窗口大小;一种是滑动的窗口。这个窗口大小就是我们一次传输几个数据,==对所有数据帧按顺序赋予编号,发送方在发送过程中始终保持着一个发送窗口,只有落在发送窗口内的帧才允许被发送;同时接收方也维持着一个接收窗口,只有落在接收窗口内的帧才允许接收。==这样通过调整发送方窗口和接收方窗口的大小可以实现流量控制。

==TCP滑动窗口技术通过动态改变窗口大小来调节两台主机间数据传输。==每个TCP/IP主机支持全双工数据传输,因此TCP有两个滑动窗口:一个用于接收数据,另一个用于发送数据。TCP使用肯定确认技术,==其确认号指的是下一个所期待的字节。==

假定发送方设备以每一次三个数据包的方式发送数据,也就是说,窗口大小为3。发送方发送序列号为1、2、3的三个数据包,接收方设备成功接收数据包,用序列号4(窗口大小+1)确认。发送方设备收到确认,继续以窗口大小3发送数据。当接收方设备要求降低或者增大网络流量时,可以对窗口大小进行减小或者增加,本例降低窗口大小为2,每一次发送两个数据包。==当接收方设备要求窗口大小为0,表明接收方已经接收了全部数据,或者接收方应用程序没有时间读取数据,要求暂停发送。==发送方接收到携带窗口号为0的确认,停止这一方向的数据传输。

先看下面一张图来分析一下固定窗口大小有什么问题。 img

注意:这里应该是ack而不是ACK,ACK是控制位中的一位,为 1 表示确认号有效,为 0 表示报文中不包含确认信息,忽略确认号字段。

这里我们可以看到假设窗口的大小是1,也是就每次只能发送一个数据只有接受方对这个数据进行确认了以后才能发送第2个数据。我们可以看到发送方每发送一个数据,接受方就要给发送方一个ACK对这个数据进行确认。==只有接受到了这个确认数据以后发送方才能传输下个数据。== 这样我们考虑一下如果说窗口过小,那么当传输比较大的数据的时候需要不停的对数据进行确认,这个时候就会造成很大的延迟。如果说窗口的大小定义的过大。我们假设发送方一次发送100个数据。但是接收方只能处理50个数据。这样每次都会只对这50个数据进行确认。发送方下一次还是发送100个数据,但是接受方还是只能处理50个数据。这样就避免了不必要的数据来拥塞我们的链路。所以我们就引入了滑动窗口机制,窗口的大小并不是固定的而是根据我们之间的链路的带宽的大小,这个时候链路是否拥护塞。接受方是否能处理这么多数据了。

结合下图看看滑动窗口是如何工作的 img

首先是第一次发送数据这个时候的窗口大小是根据链路带宽的大小来决定的。我们假设这个时候窗口的大小是3。这个时候接受方收到数据以后会对数据进行确认告诉发送方我下次希望手到的是数据是多少。这里我们看到接收方发送的ACK=3(这是发送方发送序列2的回答确认,下一次接收方期望接收到的是3序列信号)。这个时候发送方收到这个数据以后就知道我第一次发送的3个数据对方只收到了2个。就知道第3个数据对方没有收到。下次在发送的时候就从第3个数据开始发。这个时候窗口大小就变成了2img

这个时候发送方发送2个数据。

img

看到接收方发送的ACK是5就表示他下一次希望收到的数据是5,发送方就知道我刚才发送的2个数据对方收了这个时候开始发送第5个数据。

这就是滑动窗口的工作机制,当链路变好了或者变差了这个窗口还会发生变化,并不是第一次协商好了以后就永远不变了。

滑动窗口协议,是TCP使用的一种流量控制方法。==该协议允许发送方在停止并等待确认前可以连续发送多个分组。==由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。 只有在接收窗口向前滑动时(与此同时也发送了确认),发送窗口才有可能向前滑动。 收发两端的窗口按照以上规律不断地向前滑动,因此这种协议又称为滑动窗口协议。当发送窗口和接收窗口的大小都等于1时,就是停止等待协议。

参照下面:

TCP 拥堵

计算机网络中的带宽、交换结点中的缓存及处理机等都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏,这种情况就叫做拥塞

eagle 怎么解决 TCP 拥堵?

通过拥塞控制来解决。拥堵控制,就是防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致过载。*注意,拥塞控制和流量控制不同,前者是一个*全局性的过程,而后者指点对点通信量的控制。

拥塞控制的方法主要有以下四种:

  • 1、慢开始。
  • 2、拥塞避免。
  • 3、快重传。
  • 4、快恢复。

1)慢开始

不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。

2)拥塞避免

拥塞避免算法,让拥塞窗口缓慢增长,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1 ,而不是加倍,这样拥塞窗口按线性规律缓慢增长。

慢开始和拥塞避免算法的实现举例

3)快重传

快重传,要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方),而不要等到自己发送数据时捎带确认。

快重传算法规定,发送方只要一连收到三个重复确认,就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

快重传的示意图

4)快恢复

快重传配合使用的还有快恢复算法,当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把 ssthresh 门限减半。

  • 但是接下去并不执行慢开始算法:因为如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。
  • 所以此时不执行慢开始算法,而是将 cwnd 设置为 ssthresh 的大小,然后执行拥塞避免算法。

从连续收到三个重复的确认转入拥堵避免

四、UDP

UDP(User Data Protocol,用户数据报协议),是与 TCP 相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去。

主要特点如下:

  • UDP 是无连接的。
  • UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态(这里面有许多参数)。
  • UDP 是面向报文的。
  • UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低。

==对实时应用很有用,如 直播,实时视频会议等==

  • UDP 支持一对一、一对多、多对一和多对多的交互通信。
  • UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部要短。

UDP在应用层协议中的应用

  • DNS :用于域名解析服务,将域名地址转换为 IP 地址。DNS 用的是 53 号端口。
  • SNMP :简单网络管理协议,使用 161 号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
  • TFTP(Trivial File Transfer Protocol):简单文件传输协议,该协议在熟知端口 69 上使用 UDP 服务。

【重要】TCP 与 UDP 的区别

TCP(Transmission Control Protocol)和 UDP(User Datagram Protocol) 协议属于传输层协议,它们之间的区别包括:

TCP 与 UDP 的区别

  • TCP 是面向连接的;UDP 是无连接的。
  • TCP 是可靠的;UDP 是不可靠的。
  • TCP 只支持点对点通信;UDP 支持一对一、一对多、多对一、多对多的通信模式。
  • TCP 是面向字节流的;UDP 是面向报文的。
  • TCP 有拥塞控制机制;UDP 没有拥塞控制,适合媒体通信。
  • TCP 首部开销(20 个字节),比 UDP 的首部开销(8 个字节)要大。

TCP数据流模式和UDP数据报模式

所谓的“流模式”,是指TCP 发送端发送几次数据和接收端接收几次数据是没有必然联系的

  • 比如你通过 TCP 连接给另一端发送数据,你只调用了一次 write ,发送了 100 个字节,但是对方可以分 10 次收完,每次 10 个字节;你也可以调用 10 次 write ,每次 10 个字节,但是对方可以一次就收完。
  • 原因:这是因为 TCP 是面向连接的,一个 Socket 中收到的数据都是由同一台主机发出,且有序地到达,所以每次读取多少数据都可以。

所谓的“数据报模式”,是指 UDP 发送端调用了几次 write ,接收端必须用相同次数的 read 读完

  • UDP 是基于报文的,在接收的时候,每次最多只能读取一个报文,报文和报文是不会合并的,如果缓冲区小于报文长度,则多出的部分会被丢弃。
  • 原因:这是因为 UDP 是无连接的,只要知道接收端的 IP 和端口,任何主机都可以向接收端发送数据。这时候,如果一次能读取超过一个报文的数据,则会乱套。

参照:TCP流模式和UDP数据报模式的区别

UDP 报文的格式

UDP 报文格式

  • 16 位 * 4 = 64 位 = 8 字节。

五、DNS

  • 域名解析,www.xxx.com 转换成 IP ,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的 IP 数串。
  • DNS 协议运行在 UDP 协议之上,使用端口号 53 。

主机解析域名的顺序

  1. 浏览器缓存
  2. 找本机的 hosts 文件
  3. 路由缓存
  4. 找 DNS 服务器(本地域名、顶级域名、根域名)

DNS 使用的协议

参见 《DNS使用的是 TCP 协议还是 UDP 协议》 文章。

既使用 TCP 又使用 UDP 。

  • 区域传送时使用 TCP 协议。
  • 辅域名服务器会定时(一般是 3 小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用 TCP 而不是 UDP ,因为数据同步传送的数据量比一个请求和应答的数据量要多得多。
  • TCP 是一种可靠的连接,保证了数据的准确性。
  • 域名解析时使用 UDP 协议。
  • 客户端向 DNS 服务器查询域名,一般返回的内容都不超过 512 字节,用 UDP 传输即可。

UDP 报文的最大长度为 512 字节。

  • 不用经过 TCP 三次握手,这样 DNS 服务器负载更低,响应更快。虽然从理论上说,客户端也可以指定向 DNS 服务器查询的时候使用 TCP ,但事实上,很多 DNS 服务器进行配置的时候,仅支持 UDP 查询包。

六、HTTP

HTTP 协议,是 Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

HTTP 是一个无状态的协议。无状态是指客户机(Web 浏览器)和服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息。HTTP 遵循请求(Request)/应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有 HTTP 连接都被构造成一套请求和应答。

主要特点如下:

  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST 等等。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。
  • 数据格式灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由Content-Type 加以标记。
  • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

主要指的是不使用 Keep-Alive 机制的情况下。

  • 无状态:HTTP 协议是无状态协议。无状态,是指协议对于事务处理没有记忆能力。无状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

无状态,所以更容易做服务的扩容,支撑更大的访问量。

  • 支持 B/S 及 C/S 模式。

另外,HTTP 协议已经不仅仅使用在浏览器上。在前后端分离的架构中,又或者微服务架构的内部通信中,HTTP 因为其数据格式的通用性,和语言无关,被大规模使用。

HTTP 基本格式

详细的,可以看看 《猫哥网络编程系列:详解 BAT 面试题》 文章。

eagle HTTP 请求格式

HTTP 请求格式

  • 请求行:用来说明请求类型,要访问的资源以及所使用的 HTTP 版本。
  • 请求头部:紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息从第二行起为请求头部。

    • HOST ,将指出请求的目的地。
    • User-Agent ,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础。该信息由你的浏览器来定义,并且在每个请求中自动发送等等
  • 空行:请求头部后面的空行是必须的。
  • 请求数据:也叫主体,可以添加任意的其他数据。

HTTP 响应格式

HTTP 响应格式

  • 状态行:由 HTTP 协议版本号、状态码、状态消息三部分组成。
  • 消息报头:用来说明客户端要使用的一些附加信息。
  • 空行:消息报头后面的空行是必须的。
  • 响应正文:服务器返回给客户端的文本信息。

URI 和 URL 的区别

1. URI

Web上可用的每种资源如HTML文档、图像、视频片段、程序等都是一个来URI来定位的; URI一般由三部组成:

①访问资源的命名机制 ②存放资源的主机名 ③资源自身的名称,由路径表示,着重强调于资源。

2. URL

URL是Internet上用来描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,特别是著名的Mosaic。 采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。 URL一般由三部组成

①协议(或称为服务方式) ②存有该资源的主机IP地址(有时也包括端口号) ③主机资源的具体地址。如目录和文件名等

《URI 和 URL 的区别》 文章。

HTTP 协议请求方法

  • GET: 对服务器资源的简单请求。
  • POST: 用于发送包含用户提交数据的请求。
  • HEAD:类似于 GET 请求,不过返回的响应中没有具体内容,用于获取报头。
  • PUT:传说中请求文档的一个版本。
  • DELETE:发出一个删除指定文档的请求。
  • TRACE:发送一个请求副本,以跟踪其处理进程。
  • OPTIONS:返回所有可用的方法,检查服务器支持哪些方法。
  • CONNECT:用于 SSL 隧道的基于代理的请求。

GET 和 POST 的区别

请求方式数据位置明文密文数据安全长度限制应用场景
GETHTTP 请求的 path 中明文不安全长度较小,一般 2k查询数据
POSTHTTP 请求 body 中可明可密安全支持较大数据传输修改数据
  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET产生的URL地址可以被添加到书签,而POST不可以。
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST没有。
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。
  • GET 请求可被缓存;POST 请求不会被缓存。
  • GET 请求可被收藏为书签;POST 不能被收藏为书签。
  • 参见 《99%的人理解错 HTTP 中 GET 与 POST 的区别》
  • 对于 GET 方式的请求,浏览器会把 HTTP header 和 data 一并发送出去,服务器响应 200(返回数据)。
  • 而对于 POST,浏览器先发送 header ,服务器响应 100 continue ,浏览器再发送 data ,服务器响应 200 ok(返回数据)。
  • 本质上来说:get和post本质上都是基于TCP/IP的HTTP协议的请求方式,也就是说这两者本质上TCP连接。此外,要注意:==GET产生一个TCP数据包;POST产生两个TCP数据包。==

也就是说,GET 只需要汽车跑一趟就把货送到了,而 POS T得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。

ps:不过要注意,POST 具体发几次,也和浏览器的实现有关系。例如:Firefox 只发一次。 ps2:据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的 TCP 在验证数据包完整性上,有非常大的优点。

HTTP相关状态码

  • 1×× : 请求处理中,请求已被接受,正在处理
  • 2×× : 请求成功,请求被成功处理

    • 200 OK // 客户端请求成功
  • 3×× : 重定向,要完成请求必须进行进一步处理

    • 301 Moved Permanently // 永久重定向,使用域名跳转
    • 302 Found // 临时重定向,未登陆的用户访问用户中心重定向到登录页面
  • 4×× : 客户端错误,请求不合法

    • 400 Bad Request // 客户端请求有语法错误,不能被服务器所理解
    • 401 Unauthorized // 请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用
    • 403 Forbidden // 服务器收到请求,但是拒绝提供服务
    • 404 Not Found // 请求资源不存在,eg:输入了错误的 URL
  • 5×× : 服务器端错误,服务器不能处理合法请求

    • 500 Internal Server Error // 服务器发生不可预期的错误
    • 502 Bad Gateway //作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
    • 503 Server Unavailable // 服务器当前不能处理客户端的请求,一段时间后可能恢复正常
    • 504 Gateway Time-out //网关超时,这个有时候Nginx会抛出的异常,主要原因是请求超时,比如你想导出下载某个文件,结果文件太大,就可能请求超时了。

完整的状态码列表,可以看看 《HTTP 状态码》 文章。

forward 和 redirect 的区别

forward(转发)

是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器。浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在服务器实现的,并不是在客户端实现的所以客户端并不知道这个跳转动作,所以它的地址栏还是原来的地址.

redirect(重定向)

是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

==转发是服务器行为,重定向是客户端行为。==

区别

  1. 从地址栏显示来说 forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.

redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

  1. 从数据共享来说 forward:转发页面和转发到的页面可以共享request里面的数据. redirect:不能共享数据.
  2. 从运用地方来说 forward:一般用于用户登陆的时候,根据角色转发到相应的模块. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
  3. 从效率来说 forward:高. redirect:低.

本质区别

转发过程:

客户浏览器发送http请求----》web服务器接受此请求--》调用内部的一个方法在容器内部完成请求处理和转发动作----》将目标资源发送给客户;在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。

重定向过程:

客户浏览器发送http请求----》web服务器接受后发送302状态码响应及对应新的location给客户浏览器--》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址----》服务器根据此请求寻找资源并发送给客户。在这里 location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。

重定向,其实是两次request: ==第一次,客户端request A,服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失==。

详细的,请看 《请求转发(Forward)和重定向(Redirect)的区别》

状态码301 与 302 的区别

301,302 都是 HTTP 状态的编码,都代表着某个 URL 发生了转移,不同之处在于:

  • 301 redirect: 301 代表永久性转移(Permanently Moved)。
  • 302 redirect: 302 代表暂时性转移(Temporarily Moved)。

详细的,请看 《HTTP 返回码中 301 与 302 的区别》 文章。

HTTP、TCP、Socket 的关系

  • TCP/IP 代表传输控制协议/网际协议,指的是一系列协议族。
  • HTTP 本身就是一个协议,是从 Web 服务器传输超文本到本地浏览器的传送协议。
  • Socket 是 TCP/IP 网络的 API ,其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面。对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议。

综上所述:

  • 需要 IP 协议来连接网络
  • TCP 是一种允许我们安全传输数据的机制,使用 TCP 协议来传输数据的 HTTP 是 Web 服务器和客户端使用的特殊协议。
  • HTTP 基于 TCP 协议,所以可以使用 Socket 去建立一个 TCP 连接。

Cookies 和 Session 的区别

  • Session 在服务器端,Cookie 在客户端(浏览器)。

==Session 默认被存在在服务器的一个文件里(不是内存)。==

  • Session 的运行依赖 sessionid ,而 sessionid 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie ,同时 session 也会失效。但是,可以通过其它方式实现,比如在 url 参数中传递 sessionid 。
  • Session 可以放在文件、数据库、或内存中都可以。
  • 【关键】用户验证这种场合一般会用 Session

参照:https://blog.csdn.net/striveb/article/details/82469253#Session%E4%B8%8ECookie%E5%8C%BA%E5%88%AB

【重要】一次完整的 HTTP 请求所经历的步骤

这里的客户端,更多指的是浏览器。

  • 1、DNS 解析(通过访问的域名找出其 IP 地址,递归搜索)。

如用客户端浏览器请求这个页面:http://localhost.com:8080/index.htm 从中分解出协议名、主机名、 端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下:

协议名:http

主机名:localhost.com

端口:8080

对象路径:/index.htm

在这一步,需要域名系统 DNS 解析域名 localhost.com,得主机的 IP 地址。

  • 2、HTTP 请求,当输入一个请求时,建立一个 Socket 连接发起 TCP的 3 次握手。

把以上部分结合本机自己的信息,封装成一个 HTTP 请求数据包。

如果是 HTTPS 请求,会略微有不同。

  • 3、客户端发送请求

    • 3.1 客户端向服务器发送请求命令(一般是 GET 或 POST 请求)。

客户端的网络层不用关心应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作,无非就是通过查找路由表决定通过那个路径到达服务器。

==客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定 IP 地址的 MAC 地址,然后发送 ARP 请求查找目的地址,如果得到回应后就可以使用 ARP 的请求应答交换的 IP 数据包现在就可以传输了,然后发送 IP 数据包到达服务器的地址。==

客户机发送请求命令:建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是 MIME 信息包括请求修饰符、客户机信息和可内容。

    • 3.2客户端发送请求头信息和数据。
    • 4.1、服务器发送应答头信息。

    服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是 MIME 信息包括服务器信息、实体信息和可能的内容。

    • 4.2、服务器向客户端发送数据。
    • 5、服务器关闭 TCP 连接(4次挥手)。

    这里是否关闭 TCP 连接,也根据 HTTP Keep-Alive 机制有关。同时,客户端也可以主动发起关闭 TCP 连接。

    ==如果浏览器或者服务器在其头信息加入了这行代码 Connection:keep-alive,TCP 连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。==

    image-20190418141733778

    • 6、客户端根据返回的 HTML、CSS、JS 进行渲染。

    如下是《图解HTTP》提供的图片:HTTP 请求所经历的步骤

    HTTP1.0 和 HTTP1.1的区别

    主要是如下 8 点:

    • 1、可扩展性
    • 2、缓存
    • 3、带宽优化

    带来了分块传输

    HTTP/1.1中在请求消息中引入了range头域,它允许只请求资源的某个部分。在响应消息中Content-Range头域声明了返回的这部分对象的偏移值和长度。如果服务器相应地返回了对象所请求范围的内容,则响应码为206(Partial Content),它可以防止Cache将响应误以为是完整的一个对象。

    HTTP/1.1加入了一个新的状态码100(Continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。注意,HTTP/1.0的客户端不支持100响应码。但可以让客户端在请求消息中加入Expect头域,并将它的值设置为100-continue。

    • 【最重要】4、长连接

    HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。例如:一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。

    ==HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。==

    在HTTP/1.0中,要建立长连接,可以在请求消息中包含Connection: Keep-Alive头域,如果服务器愿意维持这条连接,在响应消息中也会包含一个Connection: Keep-Alive的头域。同时,可以加入一些指令描述该长连接的属性,如max,timeout等。

    • 5、消息传递
    • 6、Host 头域
    • 7、错误提示
    • 8、内容协商

    详细的每一点的说明,可以看 《HTTP1.0 与 HTTP1.1 的区别》 文章,特别是第 4 点【长连接】。

    HTTP1.1 支持长连接(PersistentConnection)和请求的流水线(Pipelining)。

    • 长连接(PersistentConnection):处理在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟。==在 HTTP1.1中 默认开启Connection:keep-alive ,一定程度上弥补了 HTTP1.0 每次请求都要创建连接的缺点。==
    • 请求的流水线(Pipelining):==HTTP1.1 还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。==

    推荐,在看看 《HTTP Keep-Alive 是什么?如何工作?》 文章。

    关于这一点,可能演变的问题有:

    • HTTP 的长连接是什么意思?
    • HTTP Keep-Alive 机制是什么?
    • HTTP Keep-Alive 机制和 TCP Keep-Alive 有什么区别?

    SPDY 是什么?

    HTTP Working-Group 最终决定以 SPDY/2 为基础,开发 HTTP/2 。

    2012 年,Google 如一声惊雷提出了 SPDY 的方案,优化了 HTTP1.X 的请求延迟,解决了 HTTP1.X 的安全性,具体如下:

    • 1、降低延迟

    针对 HTTP 高延迟的问题,SPDY 优雅的采取了多路复用(multiplexing)。多路复用通过多个请求 Stream 共享一个 Tcp连 接的方式,解决了 HOL blocking 的问题,降低了延迟同时提高了带宽的利用率。

    • 2、请求优先级(request prioritization)

    多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY 允许给每个 request 设置优先级,这样重要的请求就会优先得到响应。

    比如浏览器加载首页,首页的 html 内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。

    • 3、header 压缩

    前面提到 HTTP1.x 的 header 很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。

    • 4、基于 HTTPS 的加密协议传输

    大大提高了传输数据的安全性。

    • 5、服务端推送(server push)

    采用了 SPDY 的网页,例如我的网页有一个 sytle.css 的请求,在客户端收到 sytle.css 数据的同时,服务端会将 sytle.js 的文件推送给客户端。当客户端再次尝试获取 sytle.js 时就可以直接从缓存中获取到,不用再发请求了。

    和我们理解的服务端推送,有点(非常)不一样哈。

    SPDY 构成图如下:SPDY 构成图

    • SPDY 位于 HTTP 之下,TCP 和 SSL 之上,这样可以轻松兼容老版本的 HTTP 协议(将 HTTP1.x 的内容封装成一种新的 frame 格式),同时可以使用已有的 SSL 功能。

    七、HTTPS

    推荐先看下 《九个问题从入门到熟悉 HTTPS》 文章,写的很有趣~

    另外,也看看 《SSL/TLS 双向认证(一) – SSL/TLS工作原理》 文章,写的更技术向~

    简述

    HTTPS ,实际就是在 TCP 层与 HTTP 层之间加入了 SSL/TLS 来为上层的安全保驾护航,主要用到对称加密、非对称加密、证书,等技术进行客户端与服务器的数据加密传输,最终达到保证整个通信的安全性。

    img

    ==一句话概括:HTTP + 加密 + 认证 + 完整性保护 = HTTPS 。==

    SSL和TLS

    官方定义,SSL 是安全套接层(secure sockets layer);TLS 是 SSL 的继任者,叫传输层安全(transport layer security)。

    它们存在的唯一目的就是保证上层通讯安全的一套机制。它的发展依次经历了下面几个时期,像手机软件升级一样,每次更新都添加或去除功能,比如引进新的加密算法,修改握手方式等。

    • SSL1.0: 已废除
    • SSL2.0: RFC6176 ,已废除
    • SSL3.0: RFC6101 ,基本废除
    • TLS1.0: RFC2246 ,目前大都采用此种方式
    • TLS1.1: RFC4346
    • TLS1.2: RFC5246 ,没有广泛使用
    • TLS1.3: IETF 正在酝酿中

    为了下面描述方便,统一先叫 SSL 。

    SSL/TLS 协议作用

    1. 认证用户和服务器,确保数据发送到正确的客户机和服务器。

    客户端必须避免中间人攻击,即除了真正的服务器,任何第三方都无法冒充服务器。

    1. 加密数据以防止数据中途被窃取。
    2. 维护数据的完整性,确保数据在传输过程中不被改变。

    HTTPS实现的过程

    1.建立连接获取证书

    SSL 客户端通过 TCP 和服务器建立连接之后(443 端口),并且在一般的 tcp 连接协商(握 手)过程中请求证书。即客户端发出一个消息给服务器,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL 的服务器端会回应一个数据包,这里面确定了这次通信所需要的算法,然后服务器向客户端返回证书。==(证书里面包含了服务器信息:域名,申请证书 的公司,公共秘钥)。==

    2.证书验证

    Client 在收到服务器返回的证书后,判断签发这个证书的公共签发机构,并使用这个机构的公 共秘钥确认签名是否有效,客户端还会确保证书中列出的域名就是它正在连接的域名。

    3.数据加密和传输

    如果确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。然后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机可以开始进行对称加密进行通信。

    image-20190418163215509

    HTTP 和 HTTPS 的区别

    • 端口不同:HTTP 与 HTTPS 使用不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
    • 资源消耗:和 HTTP 通信相比,HTTPS 通信会由于加解密处理消耗更多的 CPU 和内存资源。
    • 开销:HTTPS 通信需要证书,而证书一般需要向认证机构申请免费或者付费购买。

    HTTPS 可以有效的防止运营商劫持,解决了防劫持的一个大问题。

    SSL 加密方式

    • 对称密钥加密,是指加密和解密使用同一个密钥的方式,这种方式存在的最大问题就是密钥发送问题,即如何安全地将密钥发给对方。
    • ==非对称加密,指使用一对非对称密钥,即公钥和私钥,公钥可以随意发布,但私钥只有自己知道。发送密文的一方使用对方的公钥进行加密处理,对方接收到加密信息后,使用自己的私钥进行解密。==

    SSL 协议,即用到了对称加密也用到了非对称加密,如下图所示:SSL workflow

    • 在建立传输链路时,SSL 首先对对称加密的密钥使用公钥进行非对称加密。

    ==注意,这里 Server 返回给 Client 的不是公钥( server.pub ),而是 server.crt 。Client 需要使用 ca.keyserver.crt 中解密出公钥( server.pub ) 。==

    • 链路建立好之后,SSL 对传输内容使用公钥( server.pub )对称加密。

    公钥传输的步骤

    1.对公钥加密

    每一个使用 HTTPS 的服务器都必须去专门的证书机构注册一个证书,证书中存储了用权威机构私钥加密的公钥。这样客户端用权威机构的公钥解密就可以了。

    现在 HTTPS 协议的握手阶段变成了四步:

    1. 客户端: 你好,我要发起一个 HTTPS 请求,请给我公钥
    2. 服务器: 好的,这是我的证书,里面有加密后的公钥
    3. 客户端: 解密成功以后告诉服务器: 这是我的 (用公钥加密后的) 对称秘钥。
    4. 服务器: 好的,我知道你的秘钥了,后续就用它传输。

    2.权威机构的公钥的传输

    可以存在电脑里,这个公钥不用传输,会直接内置在各大操作系统(或者浏览器)的出厂设置里。之所以不把每个服务器的公钥内置在电脑里,一方面是因为服务器太多,存不过来。另一方面操作系统也不信任你,凭什么你说你这个就是百度/淘宝的证书呢?

    所以各个公司要先去权威机构认证,申请证书,然后操作系统只会存储权威机构的公钥。因为权威机构数量有限,所以操作系统厂商相对来说容易管理。如果这个权威机构不够权威,乱发证书,就会取消他的资格,比如可怜的沃通。

    3. 将信息 hash 值随着信息一起传递

    哈希算法的特点是它可以压缩数据,如果从函数角度来看,不管多复杂的数据(定义域可以非常大)经过哈希算法都会得到一个值,而且这个值处在某个特定(远小于定义域的范围)值域内。相同数据的哈希结果一定相同,不相同数据的哈希结果一般不同,不过也有小概率会重复,这叫哈希冲突。

    为了确保原始证书没有被篡改,我们可以在传递证书的同时传递证书的哈希值。由于第三者无法解析数据,只能乱改,那么修改后的数据在解密后,就不可能通过哈希。

    比如说公钥就是之前的例子 Hello,我们假设哈希算法是获取字符串的最后一个字符,那么 Hello 的哈希值就是 o,所以加密字符串是 Ifmmpp。虽然公钥已知,每个人都可以解密,解密完也可以篡改,但是因为没有私钥, 所以无法正确的加密。所以它再返回给客户端的数据是无效数据,用公钥解析后会得到乱码。即使攻击者通过多次尝试碰巧能够解析,也无法通过哈希校验。

    4.可以防止第三方冒充服务器

    首先真正的服务器下发的内容,无法被别人篡改。他们有权威机构的公钥,所以可以解密,但是因为没有私钥,所以解密以后的信息无法加密。没有加密或者错误加密的信息被客户端用公钥解密以后,必然无法通过哈希校验。

    但是,如果你一开始请求的就不是真的服务器,而是一个攻击者,此时的他完全有机会进行中间人攻击。我们知道第一次握手的时候服务器会下发用于证明自己身份的证书,这个证书会用预设在设备上的公钥来解密。所以要么是经过认证的证书用权威机构的私钥加密,再用权威机构解密,要么是用非权威机构的私钥加密,然后找不到公钥解密。

    所以如果不小心安装过非权威机构的根证书,比如黑客提供的恶意证书,这时候设备上就多了一个预设的公钥,那么用恶意私钥加密的证书就能被正常解析出来。所以千万不要随便装根证书,这等于是为那些恶意证书留了一扇门。

    当然,凡是都有两面性。我们知道 Charles 可以调试 HTTPS 通信,它的原理就是需要用户安装 Charles 的根证书,然后我们的请求会被代理到 Charles 服务器,它下发的 Charles 证书才能被正确解析。另一方面,Charles 会作为客户端,从真正的服务器哪里拿到正确的 https 证书并用于后续通信。幸好 Charles 不是流氓软件,或者它的私钥一旦泄露,对用户都会造成很大的影响。

    参照 《九个问题从入门到熟悉 HTTPS》

    也就是说,通过 CA 来保证。至于 server.crt 证书是怎么申请的呢?请看 《SSL/TLS 双向认证(一) – SSL/TLS工作原理》 文章的 「CA 的证书 ca.crt 和 SSL Server 的证书 server.crt 是什么关系呢? 」 问题的解答。

    单向认证、双向认证

    • 单向认证,指的是只有一个对象校验对端的证书合法性。

    通常都是 Client 来校验服务器的合法性。那么 Client 需要一个ca.crt ,服务器需要 server.crtserver.key

    • 双向认证,指的是相互校验,Server 需要校验每个 Client ,Client 也需要校验服务器。
    • Server 需要 server.keyserver.crtca.crt
    • Client 需要 client.keyclient.crtca.crt

    1)单向认证的过程

    单向认证

    • 1、客户端向服务端发送 SSL 协议版本号、加密算法种类、随机数等信息。
    • 2、服务端给客户端返回 SSL 协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书。
    • 3、客户端使用服务端返回的信息验证服务器的合法性,包括:

      • 证书是否过期。
      • 发行服务器证书的 CA 是否可靠。
      • 返回的公钥是否能正确解开返回证书中的数字签名。
      • 服务器证书上的域名是否和服务器的实际域名相匹配

      验证通过后,将继续进行通信;否则,终止通信。

    4、客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择。

    5、服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。

    • 6、服务器将选择好的加密方案通过明文方式返回给客户端。
    • 7、客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器。
    • 8、服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。

    在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全

    2)双向认证的过程

    双向认证和单向认证原理基本差不多,只是除了客户端需要认证服务端以外,增加了服务端对客户端的认证,具体过程如下:

    双向认证

    • 1、客户端向服务端发送 SSL 协议版本号、加密算法种类、随机数等信息。
    • 2、服务端给客户端返回 SSL 协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书。
    • 3、客户端使用服务端返回的信息验证服务器的合法性,包括:

      • 证书是否过期。
      • 发型服务器证书的 CA 是否可靠。
      • 返回的公钥是否能正确解开返回证书中的数字签名。
      • 服务器证书上的域名是否和服务器的实际域名相匹配

      验证通过后,将继续进行通信;否则,终止通信。

      • 【新增】4、服务端要求客户端发送客户端的证书,客户端会将自己的证书发送至服务端。
      • 【新增】5、验证客户端的证书,通过验证后,会获得客户端的公钥。
      • 6、客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择。
      • 7、服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
    • 8、服务器将选择好的加密方案通过明文方式返回给客户端。
    • 9、客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器。
    • 10、服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。

    在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全

    如何选择单向认证还是双向认证

    • 一般一个站点很多用户访问就用单向认证。
    • 企业接口对接就用双向认证。

    如果想要提高 APP 的安全级别,也可以考虑双向认证。因为,APP 天然方便放入客户端证书,从而提高安全级别。

    为什么抓包工具还能抓到 HTTPS 数据包并解密成功呢

    不是说HTTPS在网络中传输的是密文吗?这个问题就是中间者攻击(man in zhe middle)。

    中间者攻击原理图

    • 解决办法,就是 HTTPS 单向验证。在客户端中内置服务器公钥,在第三步服务器返回的公钥,除了验证公钥的有效性之外,再比对公钥是不是和内置的公钥一样,不一样说明被中间者攻击了,就断开链接不在请求了。
    • 这个原理的前提是服务器的私钥没有泄露,客户端的代码不会被破解,道高一尺魔高一丈。信息安全就是在合理的范围内,选择比较合适的加密方法,没有绝对论,只有相对论。在某个范围内比较安全。

    HTTPS 握手对性能的影响

    TCP 有三次握手,再加上 HTTPS 的四次握手,影响肯定有,但是可以接受。

    • 首先,HTTPS 肯定会更慢一点,时间主要花费在两组 SSL 之间的耗时和证书的读取验证上,对称算法的加解密时间几乎可以忽略不计。
    • 而且如果不是首次握手,后续的请求并不需要完整的握手过程。客户端可以把上次的加密情况直接发送给服务器从而快速恢复,具体细节可以参考 《图解 SSL/TLS 协议》
    • 除此以外,SSL 握手的时间并不是只能用来传递加密信息,还可以承担起客户端和服务器沟通 HTTP2 兼容情况的任务。因此从 HTTPS 切换到 HTTP2.0 不会有任何性能上的开销,反倒是得益于 HTTP2.0 的多路复用等技术,后续可以节约大量时间。
    • 如果把 HTTPS2.0 当做目标,那么 HTTPS 的性能损耗就更小了,远远比不上它带来的安全性提升。

    八、HTTP2

    HTTP2 和 HTTP1.1 的区别

    HTTP2.0简述

    HTTP2.0 ,可以说是SPDY的升级版(其实原本也是基于SPDY设计的),但是,HTTP2.0 跟 SPDY 仍有不同的地方,如下:

    • HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS 。
    • HTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE

    HTTP2.0 和 HTTP1.X 相比的新特性

    • 1、新的二进制格式(Binary Format)

    HTTP1.x 的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认 0 和 1 的组合。基于这种考虑 HTTP2.0 的协议解析决定采用二进制格式,实现方便且健壮。

    • 同 SPDY 对 HTTP1.1 的改进。

      • 2、降低延迟
      • 3、多路复用(MultiPlexing)
      • 4、header 压缩
      • 5、服务端推送(server push)

    总的区别可以理解为:

    1. HTTP/2采用二进制格式而非文本格式
    2. HTTP/2是完全多路复用的,而非有序并阻塞的——只需一个连接即可实现并行
    3. 使用报头压缩,HTTP/2降低了开销
    4. HTTP/2让服务器可以将响应主动“推送”到客户端缓存中

    Nginx 怎么做 HTTP2.0 的升级改造?

    • 1、虽然 HTTP2.0 其实可以支持非 HTTPS 的,但是现在主流的浏览器像 Chrome,Firefox 表示还是只支持基于 TLS 部署的 HTTP2.0协议,所以要想升级成 HTTP2.0 还是先升级 HTTPS 为好。
    • 2、当你的网站已经升级 HTTPS 之后,那么升级 HTTP2.0 就简单很多,如果你使用 NGINX ,只要在配置文件中启动相应的协议就可以了,可以参考 NGINX白皮书NGINX配置HTTP2.0官方指南
    • 3、使用了 HTTP2.0 那么,原本的 HTTP1.x 怎么办?这个问题其实不用担心,HTTP2.0 完全兼容 HTTP1.x 的语义,对于不支持 HTTP2.0 的浏览器,NGINX 会自动向下兼容的。

    在我们内部的微服务 API 接口,也可以做 HTTP2 的改造,可以参考如下文章:

    HTTP2.0 的多路复用和 HTTP1.X 中的长连接复用区别

    • HTTP/1.0:一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接。
    • HTTP/1.1:Pipeling(流水线) 解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会。一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞。
    • ==HTTP/2:多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行。==

    如下图所示:HTTP/1.1 对比 HTTP/2

    HTTP2.0 多路复用优点

    HTTP 性能优化的关键并不在于高带宽,而是低延迟。TCP 连接会随着时间进行自我「调谐」,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。

    HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。

    服务器推送

    服务端推送能把客户端所需要的资源伴随着 index.html 一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。具体如下:

    • 普通的客户端请求过程:普通的客户端请求过程
    • 服务端推送的过程:服务端推送的过程

    为什么需要头部(header)压缩?

    假定一个页面有 100 个资源需要加载(这个数量对于今天的 Web 而言还是挺保守的),而每一次请求都有 1kb 的消息头(这同样也并不少见,因为 Cookie 和引用等东西的存在),则至少需要多消耗 100kb 来获取这些消息头。==HTTP2.0 可以维护一个字典,差量更新 HTTP 头部,大大降低因头部传输产生的流量==。

    具体参考:《HTTP/2 头部压缩技术介绍》 文章。

    • 维护一份相同的静态字典(Static Table),包含常见的头部名称,以及特别常见的头部名称与值的组合。
    • 维护一份相同的动态字典(Dynamic Table),可以动态地添加内容。
    • 支持基于静态哈夫曼码表的哈夫曼编码(Huffman Coding)。

    参考与推荐如下文章:

    九、错题收集

    1.应用层基于TCP的协议:

    1. SMTP:简单邮件传输协议
    2. Telnet:远程登录协议
    3. SNMP:简单网络管理协议
    4. FTP:文件传输协议
    5. LPD:行式打印机守护进程
    6. TFTP:简单文件传输协议
    7. NFS:网络文件系统协议



    文章评论

    目录