网络请求(一)— HTTP/0.9、HTTP/1.0、HTTP/2.0、SPDY

1 网络分层

网络分层就是将网络节点所要完成的数据的发送或转发、打包或拆包,以及控制信息的加载或拆出等工作,分别由不同的硬件和软件模块来完成。

网络分层有不同的模型,有的模型分为 7 层,有的模型分为 5 层,每一层都是为了完成某种工作而设的。为了实现这些功能,需要遵守公共的规则,这个规则就叫做协议。下图是网络分层:

网络分层

网络分层从上到下分别是应用层、传输层、网络层、数据链路层、物理层。

  • 物理层:该层负责比特流在节点之间的传输,即负责物理传输(把计算机连接起来的物理手段);
  • 数据链路层:该层控制网络层和物理层之间的通信。为了保证传输,从网络层接收到的数据被分割成特定的可被物理层传输的帧。帧是用来移动数据的结构包,它不仅包括原始数据,还包括发送方和接收方的物理地址以及纠错和控制信息。其中的地址确定了帧将发送到何处,而纠错和控制信息则确保帧无差错到达。如果在传递数据时,接收点检测到所传数据中有差错,就要通知发送方重发这一帧;
  • 网络层:该层根据网络地址将原节点发出的数据包传送到目的节点,建立主机到主机之间的通信。网络层通过综合考虑发送优先权、网络阻塞程度、服务质量以及可选路由的花费来决定发送的最佳路径;
  • 传输层:计算机会为不同的应用程序分配不同的端口,传输层负责将数据可靠的传送到相应的端口(为主机上的应用程序提供端到端的通信)。传输层可以按端口号寻址、分割与重组数据、连接管理、差错控制和流量控制、纠错功能。传输层有两个重要的传输协议:TCP(传输控制协议)和 UDP(用户数据报协议)。其中,TCP 是一个可靠的面向连接的协议,UDP 是一个不可靠的、无连接的协议;
  • 应用层:规定了应用程序使用的协议(数据格式),可以加密、解密、格式化数据,建立或解除其它节点的联系。不同类型的应用程序会使用不同的协议,比如万维网应用使用 HTTP 协议、文件传送应用使用 FTP 协议、邮件传输应用使用 SMTP 协议、远程登录服务使用 TELNET 协议;

**TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇,不仅仅指的是 TCP 和 IP 两个协议,而是指一个由 FTP、SMTP、TCP、UDP、IP 等协议构成的协议簇,同时也是 Internet 最基本的协议。**TCP/IP 定义了电子设备如何连入因特网以及数据在它们之间传递的标准。

协议:为了使数据可以在网络上顺利传送,网络通信的参与方必须遵循相同的规则,比如如何建立连接,如何相互识别等,这套规则就是协议(protocol),它最终体现为网络上传输的数据包格式。协议往往分为几个层次进行定义,分层定义的意义在于某一层的协议改变不会影响到其他层次的协议。

UDP 和 TCP的特点:

  • 传输控制协议 TCP(Transmission Control Protocol):是一种可靠的,一对一的,面向连接的通信协议。
    • 在使用 TCP 传输数据时,往往需要在客户端和服务端之间建立一个“通道”,在数据传输完成后需要关闭“通道”;
    • 为了保证传输数据的准确性,TCP 将传输的数据分为若干部分,每部分的大小根据当时的网络情况设定,并在它们的首部添加校验字节。当数据接收完毕后,客户端/服务端会对数据的完整性和准确性进行校验,全部准确后才算传输完成,否则需要重新传输;
  • 用户数据报协议 UDP(User Datagram Protocol):是一种不可靠的,无连接的,可以实现一对一、一对多、多对一和多对多的通信协议。
    • 在使用 UDP 传输数据时,不需要建立通道,在数据传输完毕后也不需要将通道关闭。因此,UDP 建立连接的时间要比 TCP 建立连接的时间短;
    • 在使用 UDP 传输数据时,会一次性地把数据发送完毕,不会根据当时的网络情况来控制发送速度,只会根据给定的速率发送,这样一来,就有可能导致数据的丢失或损坏。因此,UDP 适合一次性传输少量数据的情况。接收到数据后也不会进行完整性验证,即使是数据发生错误也不会重新传输;
    • 基于以上原因可知,UDP 在数据传输方面速度更快、延迟更低、实时性更好,因此被广泛地用于通信领域和视频网站中;

TCP 和 UDP 的区别

UDP 首部格式:

UDP首部格式

用户数据报有两个字段:数据字段和首部字段,数据字段很简单,只有 8 个字节,由 4 个字段组成,每个字段的长度都是 2 个字节。 各字段意义如下:

  • 源端口号:在需要给对方回信时使用,不需要是可全用 0;
  • 目的端口号:这在终点交付报文时必须使用;
  • 长度:用户数据报 UDP 的长度,最小为 8(仅首部);
  • 校验和:用于校验用户数据报在传输过程是否出错,出错则丢弃该报文;

TCP 首部格式:

TCP首部格式:

  • 源端口和目的端口: 各占 2 个字节,分别写入源端口号和目的端口号;
  • 序号:占 4 个字节,用于对字节流进行编号,例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401;
  • 确认号:占 4 个字节,期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701;
  • 数据偏移:占 4 位,指的是数据部分距离报文段起始处的偏移量,实际上指的是首部的长度;
  • 确认 ACK: 当 ACK = 1 时确认号字段有效,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1;
  • 同步 SYN: 在连接建立时用来同步序号。当 SYN = 1,ACK = 0 时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中 SYN = 1,ACK = 1;
  • 终止 FIN: 用来释放一个连接,当 FIN = 1 时,表示此报文段的发送方的数据已发送完毕,并要求释放连接;
  • 窗口:占 2 字节,窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的;
  • 检验和: 占 2 个字节,检验和字段检验的范围包括首部和数据这两个部分。在计算检验和时,在 TCP 报文段的前面加上 12 字节的伪首部;
  • 套接字:TCP 连接的端点叫做套接字或插口。端口号拼接到 IP 地址即构成了套接字;

TCP 的三次握手:

  • 第一次握手:在建立连接时,客户端首先向服务端发送一个 SYN 同步信号,等待服务端的确认;
  • 第二次握手:服务端收到客户端发送的 SYN 同步信号后,会向客户端发送 SYN 同步信号和 ACK 确认信号;
  • 第三次握手:客户端收到服务端的 SYN 同步信号和 ACK 确认信号后,会向服务端发送 ACK 确认信号。发送完毕后,TCP 连接就建立了。

客户端和服务端通过三次握手建立 TCP 连接,当数据传输完毕后,断开连接需要四次挥手。

TCP 的四次挥手(中断连接端可以是 Client 端,也可以是 Server 端):

  • 第一次挥手:客户端发起中断连接请求,向服务端端发送 FIN 终止信号;

  • 第二次挥手:服务端接收客户端的 FIN 终止信号后,会向客户端发送 ACK 确认信号。不发送 FIN 终止信号是因为可能还有数据未传输完成;

  • 第三次挥手:当数据发送完成,服务端向客户端端发送 FIN 终止信号;

  • 第四次挥手:客户端收到 FIN 终止信号后,会向服务端发送 ACK 确认信号,服务端收到后就可以关闭连接了;

TCP 的三次握手和四次挥手

为什么要四次挥手? 客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE _WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。

什么是 HTTP 持久连接? 如果有大量的连接,每次在连接,关闭都要经历三次握手,四次挥手,这显然会造成性能低下。因此,HTTP 有一种叫做长连接(keepalive connections)的机制。它可以在传输数据后仍保持连接,当客户端需要再次获取数据时,直接使用刚刚空闲下来的连接而无需再次握手。

2 HTTP 和 HTTPS

HTTP 是一种超文本传输协议(Hypertext Transfer Protocol),是一个简单的请求—响应协议,它通常运行在 TCP 之上,指定了客户端可能发给服务器什么样的消息以及得到什么样的回应。

HTTP URL 的格式如下所示:http://host[:port][abs_path]。http 表示要通过 HTTP 协议来定位网络资源,host 表示合法的 Internet 主机域名或者 IP 地址;port 指定一个端口号,为空则使用默认端口号 80;abs_path 指定请求资源的 URI(Web 上任意可用的资源)。

2.1 HTTP/0.9

HTTP/0.9 是 1991 年发布的第一个版本,只支持一种请求方式 — GET,没有 HTTP 请求头,没有状态码,也没有版本号。 后来它的版本号才被定义成 0.9,用来和其他版本的 HTTP 区分。

HTTP/0.9 的请求只有一行:

GET /hello.html

响应也是非常简单的,只包含 html 文档本身:

<HTML>
	Hello world
</HTML>

当 TCP 建立连接之后,服务器向客户端发送 HTML 格式的字符串,发送完毕后,就关闭 TCP 连接。由于没有状态码和错误代码,如果服务器处理的时候发生错误,只会传回一个包含问题描述信息的特殊的 HTML 文件。

此时的 HTTP 是无状态的,无状态是指对事务处理没有记忆能力,如果后续处理需要前面的信息,就必须重传。比如说访问一个网站需要反复进行登录操作。

2.2 HTTP/1.0

HTTP/1.0 是 1996 年发布的版本。相比 HTTP/0.9,HTTP/1.0 主要有如下特性:

  • 丰富了传输内容,支持传输 HTML 文件以外其他类型的内容(文字、图片、视频);
  • 除了 GET 命令外,还引入了 POST 命令和 HEAD 命令;
  • 请求与响应支持 HTTP 头,增加了状态码,响应数据的一开始是一个响应状态行;

一个典型的 HTTP/1.0 的请求像这样:

GET /hello.html HTTP/1.0
User-Agent:NCSA_Mosaic/2.0(Windows3.1)

200 OK
Date: Tue, 15 Nov 1996 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html

<HTML>
一个包含图片的页面
<IMGSRC="/smile.gif">
</HTML>

此时的 HTTP 是无连接的,每次请求都要通过 TCP 三次握手,四次挥手,和服务端重新建立连接,处理完客户端的请求,并收到客户端的应答后,即断开连接。 比如说某个客户端在短时间内多次请求同一个资源,服务器并不能区别是否之前已经响应过相同的请求,所以每次都用重新响应,耗费不必要的时间和流量。

从 1996 年开始,很多浏览器与服务器都对协议进行了扩展,那就是 keep-alive 扩展协议。这个扩展协议是作为 HTTP/1.0 的补充的“实验型持久连接”出现的。keep-alive 已经不再使用了,最新的 HTTP/1.1 规范中也没有对它进行说明,只是很多应用延续了下来。

使用 HTTP/1.0 的客户端在首部中加上 Connection:Keep-Alive,请求服务端将连接保持在打开状态。服务端如果愿意将这条连接保持在打开状态,就会在响应中包含同样的首部。如果响应中没有包含 Connection:Keep-Alive 首部,则客户端会认为服务端不支持 keep-alive,会在发送完响应报文之后关闭掉当前连接。

keep-alive

通过 keep-alive 补充协议,客户端与服务器之间完成了持久连接,然而仍然存在着一些问题:

  • 在 HTTP/1.0 中 keep-alive 不是标准协议,客户端必须发送 Connection:Keep-Alive 来激活 keep-alive 连接;
  • 代理服务器可能无法支持 keep-alive,因为一些代理是"盲中继",无法理解首部的含义,只是将首部逐跳转发。所以可能造成客户端与服务端都保持了连接,但是代理不接受该连接上的数据;
2.3 HTTP/1.1

在 HTTP/1.0 发布几个月后,HTTP/1.1 就发布了。HTTP/1.1 更多的是作为对 HTTP/1.0 的完善,在 HTTP 1.1 中,主要具有如下改进:

  • 可以复用连接;
  • 增加 pipeline:HTTP 管线化是将多个 HTTP 请求整批提交的技术,而在传送过程中不需先等待服务端的回应。管线化机制须通过永久连接(persistent connection)完成。 浏览器将 HTTP 请求大批提交可大幅缩短页面的加载时间,特别是在传输延迟(lag/latency)较高的情况下。有一点需要注意的是,只有幂等的请求可以使用 pipeline,如 GET,HEAD 方法。 -
  • chunked 编码传输:该编码将实体分块传送并逐块标明长度,直到长度为 0 块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据);
  • 引入更多缓存控制机制:如 etag,cache-control - 引入内容协商机制,包括语言,编码,类型等,并允许客户端和服务器之间约定以最合适的内容进行交换;
  • 请求消息和响应消息都支持 Host 头域:在 HTTP 1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个 IP 地址。因此,Host 头的引入就很有必要了;
  • 新增了 OPTIONS、PUT、 DELETE、TRACE、CONNECT 命令;

pipeline [ˈpaɪplaɪn](常指地下的)输送管道

HTTP/1.1 采取持久连接的方式替代了 Keep-Alive。HTTP/1.1 的连接默认情况下都是持久连接,如果要显式关闭,需要在报文中加上 Connection:Close 首部,即在 HTTP/1.1 中,所有的连接都进行了复用。 然而如同 Keep-Alive 一样,空闲的持久连接也可以随时被客户端与服务端关闭。不发送 Connection:Close 不意味着服务器承诺连接永远保持打开。

虽然 HTTP/1.1 已经优化了很多点,作为一个目前使用最广泛的协议版本,已经能够满足很多网络需求,但是随着网页变得越来越复杂,甚至演变成为独立的应用,HTTP/1.1 逐渐暴露出了一些问题:

  • 通信是明文,不加密,不够安全;
  • 不验证通信方的身份,可能遭遇伪装请求;
  • 无法保护数据的完整性,数据可能遭到篡改;
  • Header 内容过大,每次请求 Header 变化不大,造成浪费;

为了解决这些问题,HTTPS 和 SPDY 应运而生。

2.4 HTTPS

HTTPS 是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版。HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。

HTTPS和HTTP

HTTPS 协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

通信线路

HTTPS 并非是应用层的一种新协议,只是 HTTP 通信接口部分用 SSL(Secure Socket Layer)和TLS(Transport Layer Security)协议代替而已。通常,HTTP 直接和 TCP 通信,当使用 SSL 时,则演变成先和 SSL 通信,再由 SSL 和 TCP 通信了。

HTTPS 通信方式:

  • 客户端使用 HTTPS 的 URL 访问服务器端,要求与服务器建立 SSL 连接;
  • 服务器接收到客户端的请求后,会将证书信息(证书中包含公钥)传送一份给客户端;
  • 客户端与服务器开始协商 SSL 连接的安全等级,也就是信息加密的等级;
  • 客户端根据双方同意的安全等级,建立会话密钥,然后利用公钥将会话密钥加密,并传送给服务器;
  • 服务器利用自己的私钥解密出会话密钥;
  • 服务器利用会话密钥加密和客户端之间的通信;

HTTPS 和 HTTP 的区别主要如下:

  • HTTPS 协议使用 ca 申请证书,由于免费证书较少,需要一定费用;
  • HTTP 是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议;
  • HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443;

SSL 不仅提供加密处理,加密方式为混合加密。而且,SSL 还是用了一种被称为证书的手段,证书是由值得信任的第三方机构颁发,用于证明服务端和客户端是实际存在的(伪造证书是极其困难的)。

2.5 SPDY

SPDY(SPeeDY)是基于 TCP 的会话层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY 并不是一种替代 HTTP 的协议,而是对 HTTP 协议的增强:

HTTP、HTTPS、SPDY

在 2010 年到 2015 年,谷歌通过实践一个实验性的 SPDY 协议,证明了一个在客户端和服务器端交换数据的另类方式。其收集了浏览器和服务器端的开发者的焦点问题,明确了响应数量的增加和解决复杂的数据传输。

在启动 SPDY 这个项目时预设的目标是:

  • 页面加载时间(PLT )减少 50%;
  • 无需网站作者修改任何内容;
  • 将部署复杂性降至最低,无需变更网络基础设施;与开源社区合作开发这个新协议;
  • 收集真实性能数据,验证这个实验性协议是否有效;
2.6 HTTP/2.0

2015年,HTTP/2.0 问世,以下是 HTTP/2.0 的特点:

  • 使用二进制分帧层:在应用层与传输层之间增加一个二进制分帧层,以此达到在不改动 HTTP 的语义,HTTP 方法、状态码、URI 及首部字段的情况下,突破 HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量。在二进制分帧层上,HTTP2.0 会将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码,其中 HTTP1.x 的首部信息会被封装到 Headers 帧,而我们的 request body 则封装到 Data 帧里面;

二进制分帧层

  • 多路复用/连接共享:对于 HTTP/1.x,针对同一域名下的请求有一定数量的限制,超过了限制数目请求会被阻塞。HTTP/2.0 采用了多路复用的方式,允许通过同一个连接发起多重的请求;

多路复用

  • 持久化连接:HTTP/2.0 都是持久化连接,客户端和服务器之间也只需要一个连接(每个域名一个连接)即可;
  • **数据流优先级:**由于请求可以并发发送了,那么如果出现了浏览器在等待关键的 CSS 或者 JS 文件完成对页面的渲染时,服务器却在专注的发送图片资源的情况怎么办呢?HTTP/2.0 对数据流可以设置优先值,这个优先值决定了客户端和服务端处理不同的流采用不同的优先级策略;
  • 服务端推送:在 HTTP/2.0 中,服务器可以向客户发送请求之外的内容,比如正在请求一个页面时,服务器会把页面相关的 logo,CSS 等文件直接推送到客户端,而不会等到请求来的时候再发送,因为服务器认为客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源;
  • 头部压缩:使用首部表来跟踪和存储之前发送的键值对,对于相同的内容,不会再每次请求和响应时发送;

头部压缩

HTTP/2.0 的新特点和 SPDY 很相似,其实 HTTP/2.0 本来就是基于 SPDY 设计的,可以说是 SPDY 的升级版。 但是 HTTP/2.0 仍有和 SPDY 不同的地方,主要有如下两点:

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

3 Http 的持久连接和 HttpClient 连接池

HTTP 协议是无状态的协议,即每一次请求都是互相独立的。因此它的最初实现是,每一个 HTTP 请求都会打开一个 TCP Socket 连接,当交互完毕后会关闭这个连接。由于 HTTP 协议是全双工的协议,所以建立连接与断开连接是要经过三次握手与四次挥手的,在这种设计中,每次发送 HTTP 请求都会消耗很多的额外资源,即连接的建立与销毁。

全双工、半双工和单工:

  • 单工:只在一个方向上传输数据;
  • 全双工:允许数据在两个方向上同时传输;
  • 半双工:允许数据在两个方向上传输,但同一时间只能在一个方向上传输,可以理解为切换的单工;

每次建立连接关闭连接都要三次握手、四次挥手,显然会造成效率低下。于是,HTTP 协议的也进行了发展,通过持久连接的方法来进行 Socket 连接复用。

持久化连接

从图中可以看到:

  • 在串行连接中,每次交互都要打开关闭连接;
  • 在持久连接中,第一次交互会打开连接,交互结束后连接并不关闭,下次交互就省去了建立连接的过程;

持久连接的实现有两种:HTTP/1.0+ 的 keep-alive 与 HTTP/1.1 的持久连接。

HttpClient 如何生成持久连接?HttpClient 中使用了连接池来管理持有连接,同一条 TCP 链路上,连接是可以复用的。HttpClient 通过连接池的方式进行连接持久化。

其实“池”技术是一种通用的设计,其设计思想并不复杂:

  • 当有第一次连接的时候建立连接;
  • 结束时对应连接不关闭,归还到池中;
  • 下次同个目的的连接可从池中获取一个可用连接;
  • 定期清理过期连接;

参考

https://zhuanlan.zhihu.com/p/49949879
https://www.jb51.net/article/141015.htm
https://zhuanlan.zhihu.com/p/89471776
简单聊下http和https
面试 HTTP ,99% 的面试官都爱问这些问题
万字长文,一文搞懂TCP、IP和HTTP、HTTPS

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值