HTTP协议
Table of Contents
1 什么是协议
网络协议是计算机之间为了实现网络通信而达成的一种“约定”或者“规则”,有了这种“约定”,不同厂商的生产设备,以及不同操作系统组成的计算机之间,就可以实现通信。
2 HTTP协议是什么?
HTTP协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol。它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传输协议。
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。
HTTP有多个版本,目前广泛使用的是HTTP/1.1版本。
3 HTTP原理
HTTP是一个基于TCP/IP通信协议来传输数据的协议,传输的数据类型为HTML文件,图片文件,查询结果等。
HTTP协议一般用于B/S架构。 浏览器作为HTTP客户端通过URL向HTTP服务器即WEB服务器发送所有请求。
我们以访问百度为例:
4 HTTP特点
- http协议支持客户端/服务端模式,也是一种请求/响应模式的协议。
- 简单快速:客户端向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。
- 灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-type加以标记。
- 无连接:限制每次连接只处理一个请求。服务其处理完请求,并收到客户的应答后,即断开连接,但是却不利于客户端与服务器保持会话连接,为了弥补这种不足,产生了两项记录http状态的技术,一个叫Cookie,一个叫Session。
- 无状态:无状态是指协议对于事务处理没有记忆,后续处理需要前面的信息,则必须重传。
5 URI和URL的区别
- URI:Uniform Resource Identifier 统一资源标识符
- URL:Uniform Resource Location 统一资源定位符
URI是用来标示一个具体的资源的,我们可以通过URI知道一个资源是什么。
URL则是用来定位具体的资源的,标示了一个具体的资源位置。互联网上的每个文件都有一个唯一的URL。
6 HTTP报文组成
6.1 请求报文构成
- 请求行:包括请求方法、URL、协议/版本
- 请求头(Request Header)
- 请求正文
6.2 响应报文构成
- 状态行
- 响应头
- 响应正文
7 常见的请求方法
- GET:请求指定的页面信息,并返回实体主体。
- POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
- HEAD:类型与get请求,只不过返回的响应中没有具体的内容,用于获取报头。
- PUT:从客户端向服务器传送的数据取代指定的文档的内容。
- DELETE:请求服务器删除指定的页面。
7.1 get请求
7.2 post请求
7.3 post请求和get请求的区别
- 都包含有请求头和请求行,post多了请求body
- get多用来查询,请求参数放在url中,不会对服务器上的内容产生作用。post用来提交。如把账户密码放入body中。
- get是直接添加到URL后面的,直接就可以在URL中看到内容,而POST是放在报文内部的,用户无法直接看到
- get提交的数据是有限制的,因为URL长度有限制,具体的长度限制视浏览器而定。而post没有。
8 响应状态码
访问一个网页时,浏览器会向web服务器发出请求。此网页所在的服务器会返回一个包含HTTP状态码的信息头用以响应浏览器的请求。
8.1 状态码分类
- 1XX:信息型,服务器收到请求,需要请求者继续操作。
- 2XX:成功型,请求成功收到,理解并处理。
- 3XX:重定向,需要进一步的操作以完成请求。
- 4XX:客户端错误,请求包含语法错误或无法完成请求。
- 5XX:服务端错误,服务器在处理请求的过程中发生了错误。
8.2 常见状态码
- 200 OK:客户端请求成功
- 301:资源(网页等)被永久转移到其它URL
- 302:临时跳转
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报文域一起使用
- 404:请求资源不存在,可能输入了错误的URL
- 500:服务器内部发生了不可预期的错误
- 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常。
9 为什么要用https
实际使用中,绝大数的网站现在都采用https协议,这也是未来互联网发展的趋势。下面是通过wireshark抓取一个博客网站登录请求过程。
可以看到访问账户密码都是明文传输,这样客户端发出的请求很容易被不法分子截取利用,因此,HTTP协议不适合传输一些敏感信息,比如:各种账户、密码等信息,使用http协议传输隐私信息非常的不安全。
9.1 一般http中存在如下问题:
- 请求信息明文传输,容易被窃听截取
- 数据的完整性未校验,容易被篡改
- 没有验证对方身份,存在冒充风险
10 什么是HTTPS?
为了解决上述HTTP存在的问题,就用到了HTTPS。
HTTPS协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。
10.1 那么SSL又是什么?
SSL(Secure Socket Layer,安全套接字层):1994年为Netscape所研发,SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。
TLS(Transport Layer Security,传输层安全):其前身是SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,1999年从3.1开始被IETF标准化并改名,发展至今已经有TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS1.3改动比较大,目前还在草案阶段,目前使用最广泛的是TLS1.1、TLS1.2。
10.2 SSL发展史(互联网加密通信)
- 1994年NetSpace公司设计SSL协议(Secure Sockets Layout)1.0版本,但未发布。
- 1995年NetSpace发布SSL/2.0版本,很快发现有严重漏洞
- 1996年发布SSL/3.0版本,得到大规模应用
- 1999年,发布了SSL升级版TLS/1.0版本,目前应用最广泛的版本
- 2006年和2008年,发布了TLS/1.1版本和TLS/1.2版本
11 浏览器在使用HTTPS传输数据的流程是什么?
- 首先客户端通过URL访问服务器建立SSL连接。
- 服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。
- 客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
- 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网络的公钥将会话密钥加密,并传送给网站。
- 服务器利用自己的私玥解密出会话密钥。
- 服务器利用会话密钥加密与客户端之间通信。
12 HTTPS的缺点
- HTTPS协议多次握手,导致页面的加载时间延长近50%
- HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗
- 申请SSL证书需要钱,功能越强大的证书费用越高
- SSL涉及到的安全算法会消耗CPU资源,对服务器资源消耗较大
13 总结HTTPS和HTTP的区别
- HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了SSL/TLS协议进行了加密处理。
- http和https使用连接方式不同,默认端口也不一样,http是80,https是443。
14 HTTP/1.0
14.1 简介
1996年5月,HTTP/1.0 版本发布,内容大大增加。
首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。
其次,除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。
再次,HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
14.2 Content-Type 字段
关于字符的编码,1.0版规定,头信息必须是ASCII码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。
14.3 Content-Encoding 字段
由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。
Content-Encoding: gzip Content-Encoding: compress Content-Encoding: deflate
客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。
Accept-Encoding: gzip, deflate
14.4 缺点
HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。
TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。
为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。
Connection: keep-alive
这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。
Connection: keep-alive
一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。
15 HTTP/1.1
1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。
15.1 持久连接
1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。
客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。
Connection: close
目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。
15.2 管道机制
1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。
举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。
15.3 Content-Length 字段
一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。
Content-Length: 3495
上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。
在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。
15.4 分块传输编码
使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。
对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。
因此,1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。
Transfer-Encoding: chunked
每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。
15.5 其他功能
1.1版还新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。
另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。
Host: www.example.com
有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础。
15.6 缺点
虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。
为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。
16 SPDY 协议
2009年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。
这个协议在Chrome浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。
17 HTTP/2
2015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。
17.1 二进制协议
HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。
二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
17.2 多工
HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"。
举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。
这样双向的、实时的通信,就叫做多工(Multiplexing)。
17.3 数据流
因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。
客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。
17.4 头信息压缩
HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。
HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
17.5 服务器推送
HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。
常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。