http 二进制_计算机网络-HTTP

HTTP请求

当我们通过DNS解析获取到对应的服务IP地址,接下来就可以进行HTTP请求了。

那么什么是HTTP请求呢?HTTP请求本质上是把HTTP报文通过被包裹在TCP报文内的方式,发送到服务端指定端口的过程。

TCP概念我们之后会说,这里首先简单的介绍一下HTTP请求的基础概念:请求报文响应报文

请求报文

当我们发出一个HTTP请求时,我们的HTTP请求可以用下图来概括

89ee7e8538bcc8cec6300d90569a2006.png

其中1,2,3为请求行,4为请求头,5为请求体。所以我们把HTTP请求组成是这样的

871a3c27ab463cf04d1e333b9ecdd439.png

值得我们注意的是:1. 请求行中的请求协议版本。(不同的http版本会有不同的特性,我们做优化时需要考虑到http协议的特性去做)2. 请求头中的客户端信息。(我们之后做HTTP缓存的优化时就要应用到这里的相关属性),这里我们只需要对应请求报文有个大概的了解即可。

响应报文

当我们的服务器收到请求时,会给我们返回一些信息,这就是HTTP的响应报文。响应报文和我们的请求报文类似,它大概长这个样子

4857c6113925797fff4072b5d14eb4c8.png

其中1、2为响应行,3为响应头,4为响应体,看起来和HTTP请求报文的结构类似,HTTP响应组成是这样的

7777af3b3f373fd796128fe5cb119e02.png

这里我们需要注意的:1. 状态码&状态描述。(这里可以快速定位分析多种响应状态)2. 响应头中的服务端信息。(我们之后做HTTP缓存的优化时也要应用到这里的相关属性)

其实我们HTTP基本上就由HTTP请求HTTP响应两部分组成。目前我们对于HTTP请求报文和响应报文已经有一个比较简单的大体认知,之后我们讲把之前提到的几个关键点逐步展开进行分析。另外HTTP还有一个兄弟叫HTTPS,我们也会介绍一下HTTPS的实现原理。所以基本上HTTP这里的知识点有以下几部分:

  • HTTP协议版本特征,以及HTTP不同版本协议的区别
  • 结合HTTP请求头与响应头进行HTTP缓存策略
  • HTTP状态码与状态描述
  • HTTPS

HTTP版本区别

HTTP 0.9

只支持GET请求、只响应HTML文件,无状态码和错误代码

HTTP 0.9 HTML文档传输

<!-- HTTP Request -->
GET /mypage.html
<!-- HTTP Response -->
<HTML>
这是一个非常简单的HTML页面
</HTML>

HTTP 1.0

相比于0.9,1.0版本在可用性上做了极大的拓展,新增特性如下:

  1. 在请求头中增加版本协议信息用来区别HTTP版本
  2. 新增状态码
  3. 新增HTTP头
  4. 由于新增的HTTP头中的Content-Type可以指定其他的文本解析方式,所以可以传输HTML类型之外的文件

HTTP 1.0 HTML文档传输

<!-- HTTP Request -->
GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
<!-- HTTP Response -->
200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
<HTML> 
一个包含图片的页面
  <IMG SRC="/myimage.gif">
</HTML>

HTML 1.0 其他文件传输(此处以图片为例)

<!-- HTTP Request -->
GET /myimage.gif HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
<!-- HTTP Response -->
200 OK
Date: Tue, 15 Nov 1994 08:12:32 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/gif
(这里是图片内容)

HTTP 1.1

HTTP 1.0由于实现方式不一致导致在各个地方使用混乱,为了解决一致性问题,HTTP 1.1版本发布,这也是我们目前最常见的HTTP版本。

HTTP 1.1版本相比于1.0版本,不仅消除了大量歧义内容,同时也引进了如下的功能改进。

  1. 持久化链接(支持TCP链接复用)
  2. 支持管线化技术(pipelining:在上一个请求响应之前可以发送第二个请求)但可惜的是只存在理论阶段,并没有被实现支持

8bf28bea879dfb19bb14c906b609ed51.png
  1. 支持响应分块:chunked
  2. 支持额外的缓存控制特性
  3. If-Modefied-Since
  4. If-Unmodified-Since
  5. If-Match
  6. If-None-Match
  7. ET-tag
  8. 支持内容协商机制(客户端和服务端之间按照最合适的语言编码类型进行传输):Accept-XXX
  9. 支持Host头(这个功能使不同的域名可以配置在同一个IP服务器下面):Host

HTTP 1.1 传输

<!-- HTTP Request -->
GET /en-US/docs/Glossary/Simple_header HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/en-US/docs/Glossary/Simple_header
<!-- HTTP Response -->
200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Wed, 20 Jul 2016 10:55:30 GMT
Etag: "547fa7e369ef56031dd3bff2ace9fc0832eb251a"
Keep-Alive: timeout=5, max=1000
Last-Modified: Tue, 19 Jul 2016 00:59:33 GMT
Server: Apache
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding
REST:也是因为HTTP拓展到Web应用,原来HTTP只读(其他逻辑都在服务器)的方式已经不能被满足了。所以新的HTTP使用模式(representational state transfer)被设计出来,它让我们可以通过不同的请求方式(API)来查看/操作数据,而不是服务器进行修改,这就是我们的REST模式

HTTP 2.0

由于网页应用的复杂度越来越高,更多的请求被使用HTTP协议进行传输。而使用HTTP 1.1面对一些场景会有着性能问题,比如说:

  1. 队头阻塞:HTTP 1.1无法通过单个链接进行并发请求,所以浏览器需要开启多个链接加快进程。
  2. 昂贵的链接:由于1和浏览器的域名链接限制,导致网站请求资源的性能瓶颈。
  3. HTTP管线化:当有一个大/慢的请求,使用管线化技术会导致后续请求都受影响。
HTTP管线化瓶颈:就像在超市收银台或者银行柜台排队时一样,你并不知道前面的 顾客是干脆利索的还是会跟收银员/柜员磨蹭到世界末日(不管怎么说,服务器(即收银员/柜员)是要按照顺序处理请求的,如果 前一个请求非常耗时(顾客磨蹭),那么后续请求都会受到影响。

为了解决这些问题,HTTP 2.0应运而生,HTTP 2.0拥有以下特性:

  1. 二进制分帧(由文本协议转化为二进制协议)
  2. 多路复用(并行的请求可以在同一链接中进行,解除了HTTP 1.x的顺序和阻塞约束)
  3. 压缩headers(去除了传输重复数据,比如协议之类的只会传输一次)
  4. 支持服务器推送缓存
  5. 支持Alt-Svc(允许给定资源的位置和资源鉴定),允许更智能的CDN缓冲机制
  6. 支持Client-Hints(通过传输屏幕分辨率、设备尺寸... 传输合适的响应式资源,如:对应图片资源)
  7. cookie引入安全前缀以保证cookie没有被修改过

其中最重要的特性就是多路复用,它解决了HTTP 1.1中的队头阻塞问题。那么HTTP 2.0的多路复用是如何实现的呢?

首先明确一个概念:HTTP 2.0的多路复用和HTTP 1.1开启keep-alive是不一样的,keep-alive虽然开启之后也可以使用一条TCP链接,但是本质上还是属于一问一答的形式,也就是一条传输完才可以传输下一条。而HTTP 2.0中的多路复用就不一样了,多路复用可以并发好几个请求在一条TCP链接中进行传输,也就是一个域名下面的多个资源一起请求和传输。

那么聪明的小伙伴一定有问题了:那么多条请求传输,HTTP 2.0是如何做到数据不会相互污染呢?这就要得益于HTTP 2.0的两个重要概念:帧(frame)和流(steam)。

这是HTTP帧:

d0f540609962f6056d276f51389285d4.png

这是HTTP流:

59332ea5fb665cd7c9462532456749fb.png

我们之前有说过HTTP 2.0讲文本协议转化为二进制协议,我们的HTTP 2.0传输就是基于二进制帧的。在HTTP 2.0中每条TCP链接里面会存在多条双向数据流,里面的每个数据流都会有一个唯一标识和优先级。而流里面就是由我们的二进制帧组成,二进制帧里面会有头部信息标识来标明自己属于哪一条数据流。

通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。

那为什么HTTP1.1版本不可以呢?

原因是:HTTP/1.1 不是二进制传输,而是通过文本进行传输。由于没有流的概念,在使用并行传输(多路复用)传递数据时,接收端在接收到响应后,并不能区分多个响应分别对应的请求,所以无法将多个响应的结果重新进行组装,也就实现不了多路复用。

HTTPS

从上面我们可以看到HTTP协议随着不断的演进,传输的效率变得越来越高。但是除了提高传输效率,我们的传输安全性也是一个不可忽略的大问题,我们之前在介绍HTTP请求时曾说过:HTTP请求本质上是把HTTP报文通过被包裹在TCP报文内的方式,发送到服务端指定端口的过程。那么如果我们的请求被拦截,HTTP报文就会被读取/修改,就会导致我们的信息泄露。

为了避免这种情况的发生,我们想到了一个方法:把HTTP报文先进行一次加密(SSL/TSL),然后再把加密后的HTTP报文放进TCP报文中,这样就算是请求被拦截,但是由于HTTP报文已经被加密,别人也就获取不到我们的真实信息了,这就是HTTPS。

SSL和TSL的加密方式分为:对称加密和非对称加密,其中原理会涉及到私钥、公钥的概念。想要更详细的了解可以参考这里

HTTP状态码与状态描述

HTTP状态码是HTTP中很重要的概念知识,通过HTTP状态码的返回我们可以快速的定位响应状态,接下来我们大体的对于状态码进行一个大体介绍:

  • 1XX:消息,代表进行中状态
  • 100:表明部分请求服务器已接收,需继续发送剩余响应
  • 2XX:已完成状态
  • 200:成功
  • 202:成功但未处理
  • 204:成功但无返回
  • 3XX:转发/重定向
  • 301:永久移动的转发/重定向
  • 302:临时移动的转发/重定向
  • 304:not Modified未修改,缓存
  • 4XX:请求/客户端错误
  • 400:服务器不理解请求语法
  • 403:服务器拒绝访问
  • 404:资源找不到
  • 412:未满足前提条件
  • 5XX:服务端错误
  • 500:未知错误
  • 503:服务器过载/维护中

HTTP缓存

试想一下,如果客户端发起的每个请求都需要服务器进行计算响应,那并发数将会收到极大的限制。此时缓存可以说是一个十分重要的优化手段,合理的缓存策略可以极大的减少请求的开销。接下来我们就来介绍一下HTTP缓存。

宏观上HTTP缓存可以分为两大类:私有缓存(强缓存)共享缓存(协商缓存)

私有缓存可以大致理解为是我们本地浏览器所做的缓存,当这个窗口被关闭后里面的缓存就失效了,由于这个缓存是存在于我们本地的浏览器中,并不一定与别人的客户端进行共享,所以叫做私有缓存。

而共享缓存可以理解为是服务器的缓存,无论是哪个用户请求回来都会读取这部分缓存内容,所以叫做共享缓存。

私有缓存

  • Pragma:HTTP 1.0中的缓存兼容字段
  • Expires:缓存有效时间,会与本机时间进行对比,超出则请求资源(但是由于对比的是本机时间,所以不一定准确)

Expires: Wed ,21 Oct 2015 07:28:00 GMT

  • Expires为0,则表示资源已过期
  • 若存在Cache-Control头且值为max-ages-max-age,则Expires字段失效
  • Cache-Control:缓存策略
  • no-store:无缓存
  • no-cache:缓存,但是需要服务器验证(验证Last-Modified、ETag等字段)
  • max-age:相对过期时间,单位为s

共享缓存

  • (响应)Last-Modified:文件的最后修改时间
  • (请求)If-Modified-Since:比较资源最后的更新时间是否一致,一致304,不一致200
  • (请求)If-Unmodified-Since:日期之后,且未更新才接受,否则412(断点续传)
  • (响应)Etag:资源特定标识
  • (请求)If-Match:比较Etag是否一致,一致200,不一致412
  • (请求)If-None-Match:比较Etag是否不一致,不一致200,一致304

缓存优先级

私有缓存 > 共享缓存

Cache-Control > Expires > Pragma > Tag > Last-Modified

引用

https://www.zhihu.com/question/306768582/answer/595200654

https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/14

https://segmentfault.com/a/1190000020801458?utm_source=tag-newest

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值