http全面解析,看这一篇就够了!

5,806 阅读23分钟

1.什么是http协议

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网服务器传输超文本到本地浏览器的传送协议。HTTP 是基于 TCP/IP 协议通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

什么叫不涉及数据包的传输?
http协议是传输协议,属于应用层协议,网络四层模型中,传输层负责数据包的发送和网络节点中数据包的流量控制传输等,可以想象成http协议就是快递的包装盒,每一个快递实物都是一个应用程序,http负责应用程序之间数据包装,快递员相当于传输层的tcp协议等,来发送每一个快递。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。

2.http协议有什么特点

简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、PUT、DELETE、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。

灵活:HTTP允许传输任意类型的数据对象。

无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

无状态:HTTP协议是无状态的,HTTP 协议自身不对请求和响应之间的通信状态进行保存。任何两次请求之间都没有依赖关系。直观地说,就是每个请求都是独立的,与前面的请求和后面的请求都是没有直接联系的。协议本身并不保留之前一切的请求或 响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTTP 协议设计成如此简单的。

3.Http报文格式

Http报文包括请求报文响应报文两大部分
请求报文的组成:请求行(requestline)、请求头(header)、空行和请求体四个部分组成;
响应报文的组成:状态行、响应头部、空行和响应体四个部分组成

3.1请求报文的格式

请求方法 URL HTTP/版本号
请求首部字段(可选)
空行
body(只对Post请求有效)

例如:

GET http://m.baidu.com/ HTTP/1.1
Host m.baidu.com
Connection Keep-Alive
...// 其他header

key=android

上面的例子可以很容易看出,请求行包括三个部分
请求方法、url、http版本号;

看到这里不要慌,怎么像俄罗斯套娃,这么多包括,太难了!

3.1.1请求方法

请求方法包括(又来了,包括没办法呀)请求方法常规有八种类型:

序号 方法 描述
1 GET 发送请求来获得服务器上的资源,请求体中不会包含请求数据,请求数据放在协议头中。另外get支持快取、缓存、可保留书签等。幂等
2 POST 和get一样很常见,向服务器提交资源让服务器处理,比如提交表单、上传文件等,可能导致建立新的资源或者对原有资源的修改。提交的资源放在请求体中。不支持快取。非幂等
3 HEAD 本质和get一样,但是响应中没有呈现数据,而是http的头信息,主要用来检查资源或超链接的有效性或是否可以可达、检查网页是否被串改或更新,获取头信息等,特别适用在有限的速度和带宽下。
4 PUT 和post类似,html表单不支持,发送资源与服务器,并存储在服务器指定位置,要求客户端事先知道该位置;比如post是在一个集合上(/province),而put是具体某一个资源上(/province/123)。所以put是安全的,无论请求多少次,都是在123上更改,而post可能请求几次创建了几次资源。幂等
5 DELETE 请求服务器删除某资源。和put都具有破坏性,可能被防火墙拦截。如果是https协议,则无需担心。幂等
6 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。就是把服务器作为跳板,去访问其他网页然后把数据返回回来,连接成功后,就可以正常的get、post了。
7 OPTIONS 获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等。
8 TRACE 回显服务器收到的请求,主要用于测试或诊断。一般禁用,防止被恶意攻击或盗取信息。

这八种方法其中
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT

这里有个关键字幂等性,what 啥意思呀?
幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同,

3.1.2 请求url

这个好像没什么好说的,就是一般的url连接,例如http://m.baidu.com/ 还是说点吧!
使用HTTP协议访问资源是通过URL(Uniform Resource Locator)统一资源定位符来实现的。URL的格式如下

scheme://host:port/path?query

scheme: 表示协议,如Http, Https, Ftp等;
host: 表示所访问资源所在的主机名:如:www.baidu.com;
port: 表示端口号,默认为80;
path: 表示所访问的资源在目标主机上的储存路径;
query: 表示查询条件;

例如: http://www.baidu.com/search?words=Baidu

3.1.3 http版本

http有好多版本

  • HTTP/0.9 HTTP协议的最初版本,功能简陋,仅支持请求方式GET,并且仅能请求访问HTML格式的资源。 没有首部;只能获取纯文本,请求完成后即关闭TCP连接
  • HTTP/1.0
    • 任何格式的内容都可以发送。不仅可以传输文字,还能传输图像、视频、二进制文件。
    • 除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。
    • HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
    • 新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等
  • HTTP1.1
    • 持久连接(keep-alive):TCP连接默认不关闭,可以被多个请求复用
    • 管道机制(pipelining):同一个TCP连接里面,客户端可以同时发送多个请求。但是服务器还是按照顺序响应。
    • 分块传输编码:对于动态生成的响应类容,可以使用分块传输,边生成边发送
    • 新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。
    • 客户端请求的头信息新增了Host字段,用来指定服务器的域名:有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础。
  • HTTP2.0
    • 多路复用:HTTP2建立一个TCP连接,一个连接上面可以有任意多个流(stream),消息分割成一个或多个帧在每个流里面传输。帧传输过去以后,再进行重组,形成一个完整的请求或响应。
    • 二进制帧:1.1响应是文本格式,而2.0把响应划分成了两个帧,HEADERS和DATA 是帧的类型。也就是说一条HTTP响应,划分成了两个帧来传输,并且采用二进制来编码。
    • 头信息压缩:每个请求带的一些首部字段都是相同的,例如cookie、user-agent等。HTTP2压缩首部。
    • 服务器推送:服务器端推送使得服务器可以预测客户端需要的资源,主动推送到客户端。如客户端请求index.html,服务器端能够额外推送script.js和style.css。

3.2 首部字段

这个地方字段太多!

HTTP首部字段由字段名和字段值组成,中间以":"分隔,如Content-Type: text/html.其中,同一个字段名可对应多个字段值。

HTTP的报文字段分为5种:

  • 请求报文字段
  • 应答报文字段
  • 实体首部字段
  • 通用报文字段
  • 其他报文字段
3.2.1 请求报文字段
Accept:客户端能够处理的媒体类型。如text/html, 表示客户端让服务器返回html类型的数据,如果没有,返回text
类型的也可以。媒体类型的格式一般为:type/subType, 表示优先请求subType类型的数据,如果没有,返回type类型
数据也可以。

常见的媒体类型:
文本文件:text/html, text/plain, text/css, application/xml
图片文件:iamge/jpeg, image/gif, image/png;
视频文件:video/mpeg
应用程序使用的二进制文件:application/octet-stream, application/zip

Accept字段可设置多个字段值,这样服务器依次进行匹配,并返回最先匹配到的媒体类型,当然,也可通过q参数来设置
媒体类型的权重,权重越高,优先级越高。q的取值为[0, 1], 可取小数点后3位,默认为1.0。例如:
Accept: text/html, application/xml; q=0.9, */*

Accept-Charset: 表示客户端支持的字符集。例如:Accept-Charset: GB2312, ISO-8859-1

Accept-Encoding: 表示客户端支持的内容编码格式。如:Accept-Encoding:gzip

常用的内容编码:
gzip: 由文件压缩程序gzip生成的编码格式;
compress: 由Unix文件压缩程序compress生成的编码格式;
deflate: 组合使用zlib和deflate压缩算法生成的编码格式;
identity:默认的编码格式,不执行压缩。

Accept-Language:表示客户端支持的语言。如:Accept-Language: zh-cn, en

Authorization:表示客户端的认证信息。客户端在访问需要认证的也是时,服务器会返回401,随后客户端将认证信息
加在Authorization字段中发送到服务器后,如果认证成功,则返回200. 如Linux公社下的Ftp服务器就是这种流程:
ftp://ftp1.linuxidc.com。

Host: 表示访问资源所在的主机名,即URL中的域名部分。如:m.baidu.com

If-Match: If-Match的值与所请求资源的ETag值(实体标记,与资源相关联。资源变化,实体标记跟着变化)一致时,
服务器才处理此请求。

If-Modified-Since: 用于确认客户端拥有的本地资源的时效性。 如果客户端请求的资源在If-Modified-Since指定
的时间后发生了改变,则服务器处理该请求。如:If-Modified-Since:Thu 09 Jul 2018 00:00:00, 表示如果客户
端请求的资源在2018年1月9号0点之后发生了变化,则服务器处理改请求。通过该字段我们可解决以下问题:有一个包含大
量数据的接口,且实时性较高,我们在刷新时就可使用改字段,从而避免多余的流量消耗。

If-None-Match: If-Match的值与所请求资源的ETag值不一致时服务器才处理此请求。

If-Range: If-Range的值(ETag值或时间)与所访问资源的ETag值或时间相一致时,服务器处理此请求,并返回
Range字段中设置的指定范围的数据。如果不一致,则返回所有内容。If-Range其实算是If-Match的升级版,因为它
的值不匹配时,依然能够返回数据,而If-Match不匹配时,请求不会被处理,需要数据时需再次进行请求。


If-Unmodified-Since:与If-Modified-Since相反,表示请求的资源在指定的时间之后未发生变化时,才处理请求,
否则返回412。

Max-Forwards:表示请求可经过的服务器的最大数目,请求每被转发一次,Max-Forwards减1,当Max-Forwards为0
时,所在的服务器将不再转发,而是直接做出应答。通过此字段可定位通信问题,比如之前支付宝光纤被挖断,就可通过设
置Max-Forwards来定位大概的位置。

Proxy-Authorization:当客户端接收到来自代理服务器的认证质询时,客户端会将认证信息添加到
Proxy-Authorization来完成认证。与Authorization类似,只不过Authorization是发生在客户端与服务端之间。

Range:获取部分资源,例如:Range: bytes=500-1000表示获取指定资源的第500到1000字节之间的内容,如果服务器
能够正确处理,则返回206作为应答,表示返回了部分数据,如果不能处理这种范围请求,则以200作为应答,返回完整的
数据,

Referer:告知服务器请求是从哪个页面发起的。例如在百度首页中搜索某个关键字,结果页面的请求头部就会有这个字段,
其值为https://www.baidu.com/。通过这个字段可统计广告的点击情况。

User-Agent:将发起请求的浏览器和代理名称等信息发送给服务端,例如:
User-Agent: Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/63.0.3239.84 Mobile Safari/537.36

3.2.2 应答报文字段
Age:服务端告知客户端,源服务器(而不是缓存服务器)在多久之前创建了响应。
单位为秒。

ETag: 实体资源的标识,可用来请求指定的资源。

Location:请求的资源所在的新位置。

Proxy-Authenticate:将代理服务器需要的认证信息发送给客户端。

Retry-After:服务端告知客户端多久之后再重试,一般与503和3xx重定向类型的应答一起使用。

Server:告知服务端当前使用的HTTP服务器应用程序的相关信息。

WWW-Authenticate:告知客户端适用于所访问资源的认证方案,如Basic或Digest。401的响应中肯定带有
WWW-Authenticate字段。
3.2.3 实体首部字段
Allow:通知客户端,服务器所支持的请求方法。但服务器收到不支持的请求方法时,会以405(Method Not Allowed)
作为响应。
    
Content-Encoding:告知客户端,服务器对资源的内容编码。
  
Content-Language:告知客户端,资源所使用的自然语言。
  
Content-Length:告知客户端资源的长度
  
Content-Location:告知客户端资源所在的位置。
  
Content-Type:告知客户端资源的媒体类型,取值同请求首部字段中的Accept。
  
Expires:告知客户端资源的失效日期。可用于对缓存的处理。
  
Last-Modified:告知客户端资源最后一次修改的时间。

3.2.4 通用报文字段

可在HTTP请求中使用,也可在HTTP应答中使用的报文字段。

Cache-Control:控制缓存行为;

Connection:管理持久连接,设置其值为Keep-Alive可实现长连接。

Date:创建HTTP报文的日期和时间。

Pragma:Http/1.1之前的历史遗留字段,仅作为HTTP/1.0向后兼容而定义,虽然是通用字段,当通常被使用在客户单的
请求中,如Pragma: no-cache, 表示客户端在请求过程中不循序服务端返回缓存的数据;

Transfer-Encoding:规定了传输报文主题时使用的传输编码,如Transfer-Encoding: chunked

Upgrade: 用于检查HTTP协议或其他协议是否有可使用的更高版本。

Via:追踪客户端和服务端之间的报文的传输路径,还可避免会环的发生,所以在经过代理时必须添加此字段。

Warning:Http/1.1的报文字段,从Http/1.0的AfterRetry演变而来,用来告知用户一些与缓存相关的警告信息。

3.2.5 其他报文字段

这些字段不是HTTP协议中定义的,但被广泛应用于HTTP请求中。
Cookie:属于请求型报文字段,在请求时添加Cookie, 以实现HTTP的状态记录。
Set-Cookie:属于应答型报文字段。服务器给客户端传递Cookie信息时,就是通过此字段实现的。

Set-Cookie的字段属性:

NAME=VALUE:赋予Cookie的名称和值;
expires=DATE: Cookie的有效期;
path=PATH: 将服务器上的目录作为Cookie的适用对象,若不指定,则默认为文档所在的文件目录;
domin=域名:作为Cookies适用对象的域名,若不指定,则默认为创建Cookie的服务器域名;
Secure: 仅在HTTPS安全通信是才会发送Cookie;
HttpOnly: 使Cookie不能被JS脚本访问;

如:Set-Cookie:BDSVRBFE=Go; max-age=10; domain=m.baidu.com; path=/

3.3 响应报文的格式

HTTP/版本号 返回码 返回码描述
应答首部字段(可选)
空行
body

例如下面的内容

HTTP/1.1 200 OK
Content-Type text/html;charset=UTF-8
...// 其他header

<html>...

http响应报文跟请求报文大部分内容相似;http版本号,上面已经介绍了!

返回码,有的时候也叫状态码

下面是常见的HTTP状态码:

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

http状态码的分类

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

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

http状态码列表

状态码 状态码英文名称 中文描述
100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

http基础的知识基本就这些了!这个状态码太多了,什么你全记住了,牛!

4.http的一些问题

4.1 HTTP的keep-alive是干什么的?

在早期的HTTP/1.0中,每次http请求都要创建一个连接,而创建连接的过程需要消耗资源和时间,为了减少资源消耗,缩短响应时间,就需要重用连接。在后来的HTTP/1.0中以及HTTP/1.1中,引入了重用连接的机制,就是在http请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流。协议规定HTTP/1.0如果想要保持长连接,需要在请求头中加上Connection: keep-alive。 keep-alive的优点:

  • 较少的CPU和内存的使用(由于同时打开的连接的减少了)
  • 允许请求和应答的HTTP管线化
  • 降低拥塞控制 (TCP连接减少了)
  • 减少了后续请求的延迟(无需再进行握手)
  • 报告错误无需关闭TCP连

4.2 GET和POST有什么区别?

  • 数据传输方式不同:GET请求通过URL传输数据,而POST的数据通过请求体传输。
  • 安全性不同:POST的数据因为在请求主体内,所以有一定的安全性保证,而GET的数据在URL中,通过历史记录,缓存很容易查到数据信息。
  • 数据类型不同:GET只允许 ASCII 字符,而POST无限制
  • GET无害: 刷新、后退等浏览器操作GET请求是无害的,POST可能重复提交表单
  • 特性不同:GET是安全(这里的安全是指只读特性,就是使用这个方法不会引起服务器状态变化)且幂等(幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同),而POST是非安全非幂等

这个问题面试中可能经常会问到,多少说点意思意思呀!

4.3 http不保存状态和cookie是什么?

HTTP 协议对于发送的请求和响应不做持久化处理。这时候引入了 Cookie 技术用于状态管理。Cookie 对用与登录的状态管理,没有 Cookie 这个技术的话,因为 HTTP 不保存状态,每次打开新网页都必须再次登录。 Cookie 会根据响应报文中的 Set-Cookie 字段来通知客户端自动保存 Cookie。下次请求时会自动发送 Cookie,服务器会比对数据得到状态结果。

往期文章推荐
那些年你曾经工作过的奇葩公司能有多奇葩!
Kotlin扩展和对应的java代码解析
git操作高级命令
了解一下计算机网络层吧
计算机网络基础
带你深入了解运输层
看看网络安全的一些知识吧!
是时候了解一下应用层的知识了一起来吧!
如何使用命令行卸载手机预知APP

长按二维码关注公众号,接收新的消息推送,值得期待哟!更有奇葩公司的后续传奇经历,等待与您分享,感谢您的支持!

技术干货店