计算机网络之:HTTP和HTTPS

73 阅读23分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

本文是我之前在微信公众号上的一篇文章记录。原链接为:(彻底搞懂系列之:HTTP和HTTPS)

HTTP

什么是HTTP

超文本传输协议(Hyper Text Transfer Protocol),是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据(HTML文件, 图片文件, 查询结果等),是互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。

特点

HTTP协议支持客户端/服务端模式,也是一种请求/响应模式的协议。

  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。
  • 灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。
  • 无连接:限制每次连接只处理一个请求。服务器处理完请求,并收到客户的应答后,即断开连接,但是却不利于客户端与服务器保持会话连接,为了弥补这种不足,产生了两项记录HTTP状态的技术,一个叫做Cookie,一个叫做Session。
  • 无状态:无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

HTTP发展历史

http history

HTTP/0.9

这是最早定稿的HTTP版本,这个版本中它的内容非常地简单。

  • 首先它只有一个命令GET。对应到现在的GET请求和POST请求,这些叫做HTTP的命令或者方法。
  • 它没有HEADER等描述数据的信息。因为这个时候的请求非常简单,它需要达到的目的也非常简单,没有那么多数据格式。
  • 服务器发送完内容之后,就关闭TCP连接。这里需要注意一点,这里的TCP连接和http请求是不一样的。http请求和TCP连接不是一个概念。一个http请求通过TCP连接发送,而一个TCP连接里面可以发送很多个http请求(HTTP/0.9不能这么做,但是HTTP/1.1可以这么做,而且在HTTP/2这方面会更大程度地优化,来提高HTTP协议传输的效率以及服务器的性能)。所以一个TCP连接对应的是多个http请求,一个http请求肯定是在某一个TCP连接里面进行发送的。

HTTP/1.0

这个版本和现在普遍使用的HTTP/1.1差不多,在HTTP/0.9版本基础上进行了改进。

  • 增加了很多命令。比如:POST、PUT、HEADER这些命令。
  • 增加了status code和header相关的内容。status code是用来描述服务器端处理某一个请求之后的状态的;header主要包含:请求和发送数据的描述以及对这部分数据进行操作的方法。
  • 增加了多字符集支持、多部分发送、权限、缓存等相关的内容。这些内容有利于更好地使用http请求去实现WEB服务。

HTTP/1.1

这个版本是在HTTP/1.0的基础上增加了一些功能来优化网络连接的过程。

  • 在这个版本支持了持久连接。在HTTP/1.0版本里面,一个http请求要发送就要先在客户端和服务器端之间创建一个TCP连接,创建完这个TCP连接之后,等服务器端返回完数据之后,这个TCP连接就关闭了。如果在建立完一个连接之后,它可以不关闭,之后新的http请求就可以一直在这个连接里面进行数据发送的话,它的性能和效率肯定会提升很多,HTTP/1.1已经实现了这个功能。

  • 增加了pipeline。可以在同一个TCP连接里面发送多个http请求,就是上面说的那样。但是在HTTP/1.1里面,虽然是可以在同一个TCP连接里面发送多个http请求,但是服务器端对于进来的请求,是要按照顺序进行数据返回的。因此,如果前一个请求等待时间非常长,而后一个请求处理得比较快。这个时候后一个请求不能先发送,而是要等第一个请求数据全部发送完成之后,才能进行发送,即是串行的。等待的这部分时间就体现出了与并行传输性能之间的差距。而这个在HTTP/2里面得到了优化。

  • 增加了HTTP的头host和其他一些命令。其中比较重要的就是host,有了host之后就可以在同一台服务器(物理服务器)上同时跑多个web服务。比如说一个Node.js的web服务,一个Java的web服务。通过host这个字段来表示两个服务都是请求到同一个物理服务器上,但是我要请求的是里面哪一个软件服务,Node.js还是Java?这就是通过host来进行判断的。这个host头增加的好处就是,在同一个物理服务器或者同一个集群里面可以部署很多不同的web服务来,提高了物理服务器的使用效率。

HTTP/2.0

虽然现在还没有普及,但是毫无疑问是未来的趋势。

  • 所有数据都是以二进制进行传输的。在HTTP/1.1里面大部分的数据传输是通过字符串,所以数据的分片方式是不太一样的。在HTTP/2里面所有的数据都是以帧进行传输的。
  • 正是因为有了这个好处,同一个连接里面发送多个请求时,服务器端不再需要按照顺序来返回处理后的数据了。而是可以在返回第一个请求里面数据的时候,同时返回第二个请求里面的数据。这样的并行传输能够更大限度地提高web应用的传输效率。
  • 新增头信息压缩以及推送等功能,提高了传输效率。HTTP/2其实主要就是改善了HTTP/1.1里面造成性能低下的一些问题。

HTTP消息结构

HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议,使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。

请求消息

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

http request header

  • 请求行:由请求方法、URL(包含参数)和协议版本组成
  • 请求头部:由多个key-value值组成
  • 空行:请求报文使用空行将请求头部和请求数据分隔
  • 请求数据:GET方法没有携带数据,POST方法会携带一个body

典型的请求消息: 

GET /simple.htm HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: localhost:8080
Connection: Keep-Alive

响应消息

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

http responed header

  • 状态行:由协议版本、状态码和状态值组成
  • 响应头:由多个key-value值组成
  • 空行:响应报文使用空行将响应头和响应体分隔
  • 响应体:响应数据,可以是一段HTML数据

典型的响应消息: 

HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
X-Powered-By: ASP.NET
Date: Fri, 03 Mar 2006 06:34:03 GMT
Content-Type: text/html
Accept-Ranges: bytes
Last-Modified: Fri, 03 Mar 2006 06:33:18 GMT
ETag: "5ca4f75b8c3ec61:9ee"
Content-Length: 37

<html><body>hello world</body></html>

请求方法

HTTP请求有很多种请求方法。

HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。

请求方法描述
GET请求指定的页面信息,并返回实体主体
HEAD类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头
POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改
PUT从客户端向服务器传送的数据取代指定的文档的内容
DELETE请求服务器删除指定的页面
CONNECTHTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
OPTIONS允许客户端查看服务器的性能
TRACE回显服务器收到的请求,主要用于测试或诊断
PATCH是对PUT方法的补充,用来对已知资源进行局部更新

状态码

当访问一个网页时,浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。

HTTP状态码的英文为HTTP Status Code。下面是常见的HTTP状态码:

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码可以分为5种类型:

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

具体的状态码比较多,就不在这里赘述了。

HTTPS

什么是HTTPS

HTTPS(全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的HTTP通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS在HTTP的基础下加入TLS/SSL,HTTPS的安全基础是SSL/TLS,因此加密的详细内容就需要SSL/TLS。 HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间,TLS是传输层加密协议,前身是SSL协议,由网景公司1995年发布,有时候两者不区分)。这个系统提供了身份验证与加密通讯方法。它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面。

HTTPS协议是由 HTTP 加上TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。设计目标主要有三个:

  1. 数据保密性:保证数据内容在传输的过程中不会被第三方查看。就像快递员传递包裹一样,都进行了封装,别人无法获知里面装了什么。
  2. 数据完整性:及时发现被第三方篡改的传输内容。就像快递员虽然不知道包裹里装了什么东西,但他有可能中途掉包,数据完整性就是指如果被掉包,我们能轻松发现并拒收。
  3. 身份校验安全性:保证数据到达用户期望的目的地。就像我们邮寄包裹时,虽然是一个封装好的未掉包的包裹,但必须确定这个包裹不会送错地方,通过身份校验来确保送对了地方。

HTTPS的演化史

对称加密HTTPS

如上图所示,HTTPS最开始的设计就是此种方式,传输的数据用同样的密钥进行加密,它属于对称加密,客户端和服务器双方拥有相同的密钥,信息得到安全传输,但此种方式的缺点也很明显:

  • 不同的客户端、服务器数量庞大,所以双方都需要维护大量的密钥,维护成本很高。
  • 因每个客户端、服务器的安全级别不同,密钥极易泄露。

既然使用对称加密时,密钥维护这么繁琐,那我们就用非对称加密试试,因此第二代的HTTPS就此产生了:

非对称加密HTTPS

如上图所示,客户端用公钥对请求内容加密,服务器使用私钥对内容解密,反之,服务器用私钥加密,客户端用公钥解密,但上述过程也存在缺点:

  • 公钥是公开的(也就是黑客也会有公钥),所以第 ④ 步私钥加密的信息,如果被黑客截获,其可以使用公钥进行解密,获取其中的内容。

那么既然非对称加密既然也有缺陷,那我们就将对称加密,非对称加密两者结合起来,取其精华、去其糟粕,发挥两者的各自的优势,就这样第三代HTTPS诞生了:

非对称-对称加密HTTPS

如上图所示:

  1. 第 ③ 步时,客户端说:(咱们后续会话采用对称加密吧,这是对称加密的算法和对称密钥)这段话用公钥进行加密,然后传给服务器。
  2. 服务器收到信息后,用私钥解密了这段话,提取出对称加密算法和对称密钥后,服务器说:(好的),用对称密钥加密后发回给客户端。
  3. 后续两者之间信息的传输就可以使用对称加密的方式了。

但是还是不免有存在一些问题:

  • 客户端如何获得公钥
  • 如何确认服务器是真实的而不是黑客

基于上面的问题思考:

如何获取公钥与确认服务器身份?

  1. 可不可以提供一个下载公钥的地址,会话前让客户端去下载。(缺点:下载地址有可能是假的;客户端每次在回话前都先去下载公钥也很麻烦)
  2. 或者会话开始时,服务器把公钥发给客户端。(缺点:黑客冒充服务器,发送给客户端假的公钥)

那有木有一种方式既可以安全的获取公钥,又能防止黑客冒充呢? 那就需要用到终极武器了:SSL 证书(申购)

如上图所示,在第 ② 步时服务器发送了一个SSL证书给客户端,SSL证书中包含的具体内容有:

  • 证书的发布机构CA
  • 证书的有效期
  • 公钥
  • 证书所有者
  • 签名
  • 其他信息………

客户端在接受到服务端发来的SSL证书时,会对证书的真伪进行校验,以浏览器为例说明如下:

  1. 首先浏览器读取证书中的证书所有者、有效期等信息进行一一校验
  2. 浏览器开始查找操作系统中已内置(或者浏览器内置的)的受信任的证书发布机构 CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发。
  3. 如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的。
  4. 如果找到,那么浏览器就会从操作系统(浏览器)中取出颁发者CA的公钥,然后对服务器发来的证书里面的签名进行解密。
  5. 浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比。
  6. 对比结果一致,则证明服务器发来的证书合法,没有被冒充。
  7. 此时浏览器就可以读取证书中的公钥,用于后续加密了。

所以通过发送SSL证书的形式,既解决了公钥获取问题,又解决了黑客冒充问题,一箭双雕,HTTPS加密过程也就此形成。

问题

HTTP1.X与HTTP2的区别

  • 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
  • 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
  • header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
  • 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。

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

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

具体如图:

http1 and http2

服务器推送到底是什么?

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

为什么需要头部压缩?

随着web功能越来越复杂,请求数量越来越多,假定一个页面有100个资源需要加载(这个数量对于今天的Web而言还是挺保守的), 而每一次请求都有1kb的消息头(这同样也并不少见,因为Cookie和引用等东西的存在), 则至少需要多消耗100kb来获取这些消息头。通过压缩,头部大小可以减少一半之多,如果后面重复发送请求,那么可能压缩后的头部大小只有原始大小的 1/10(HTTP2.0可以维护一个字典,差量更新HTTP头部,大大降低因头部传输产生的流量)。具体参考:HTTP/2头部压缩技术介绍。

HTTP2.0多路复用有多好?

HTTP 性能优化的关键并不在于高带宽,而是低延迟。TCP 连接会随着时间进行自我「调谐」,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。 HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。

什么是无状态协议

无状态协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息。

为什么说HTTP是无状态的协议呢?因为它的每个请求都是完全独立的,每个请求包含了处理这个请求所需的完整的数据,发送请求不涉及到状态变更。即使在HTTP/1.1上,同一个连接允许传输多个HTTP请求的情况下,如果第一个请求出错了,后面的请求一般也能够继续处理。可以看出,这种协议的结构是要比有状态的协议更简单的,一般来说实现起来也更简单,不需要使用状态机,一个循环就行了。

无状态协议有一些优点,也有一些缺点。和许多人想象的不同,会话(Session)支持其实并不是一个缺点,反而是无状态协议的优点,因为对于有状态协议来说,如果将会话状态与连接绑定在一起,那么如果连接意外断开,整个会话就会丢失,重新连接之后一般需要从头开始;而HTTP这样的无状态协议,使用元数据(如Cookies头)来维护会话,使得会话与连接本身独立起来,这样即使连接断开了,会话状态也不会受到严重伤害,保持会话也不需要保持连接本身。另外,无状态的优点还在于对中间件友好,中间件无需完全理解通信双方的交互过程,只需要能正确分片消息即可,而且中间件可以很方便地将消息在不同的连接上传输而不影响正确性,这就方便了负载均衡等组件的设计。

无状态协议的主要缺点在于,单个请求需要的所有信息都必须要包含在请求中一次发送到服务端,这导致单个消息的结构需要比较复杂,必须能够支持大量元数据,因此HTTP消息的解析要比其他许多协议都要复杂得多。同时,这也导致了相同的数据在多个请求上往往需要反复传输,例如同一个连接上的每个请求都需要传输Host、Authentication、Cookies、Server等往往是完全重复的元数据,一定程度上降低了协议的效率。

POST与PUT的区别

在了解PUT和POST区别之前我们先来学习一个新概念:

幂等性概念:幂等通俗来说是指不管进行多少次重复操作,都是实现相同的结果。

HTTP的请求方法中,GET,PUT,DELETE都是幂等操作,而POST不是,以下进行分析: 首先GET请求很好理解,对资源做查询多次,此实现的结果都是一样的。 PUT请求的幂等性可以这样理解,将A修改为B,它第一次请求值变为了B,再进行多次此操作,最终的结果还是B,与一次执行的结果是一样的,所以PUT是幂等操作。 同理可以理解DELETE操作,第一次将资源删除后,后面多次进行此删除请求,最终结果是一样的,将资源删除掉了。

POST不是幂等操作,因为一次请求添加一份新资源,二次请求后则添加了两份新资源,多次请求会产生不同的结果,因此POST不是幂等操作。

一般情况下,它们的使用方法如下:

GET /tickets # 获取ticket列表
GET /tickets/12 # 查看某个具体的ticket
POST /tickets # 新建一个ticket
PUT /tickets/12 # 更新ticket 12.
DELETE /tickets/12 #删除ticekt 12

URI和URL的区别

URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。

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

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

URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。

URL是Internet上用来描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,特别是著名的Mosaic。

采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。URL一般由三部组成:

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

拿人来举个例子,人的身份证号是URI,通过身份证号能让标识确定一个人。 那统一资源定位符URL是什么呢。也拿人做例子然后跟HTTP的URL做类比,就可以有: 动物住址协议://地球/中国/浙江省/杭州市/西湖区/某大学/14号宿舍楼/525号寝/张三.人

可以看到,这个字符串同样标识出了唯一的一个人,起到了URI的作用,所以URL是URI的子集。URL是以描述人的位置来唯一确定一个人的。在上文我们用身份证号也可以唯一确定一个人。对于这个在杭州的张三,我们也可以用:身份证号:123456789 来标识他。所以不论是用定位的方式还是用编号的方式,我们都可以唯一确定一个人,都是URl的一种实现,而URL就是用定位的方式实现的URI。

HTTP与HTTPS的区别

  • HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
  • 使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
  • HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
  • http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
  • HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源。

HTTP教程-菜鸟教程

HTTP和HTTPS协议