前端必备HTTP技能之请求头响应头格式以及请求方法简述

前端必备HTTP技能之请求头响应头格式以及请求方法简述,第1张

http协议中,客户端和服务端通过发送纯文本(ASCII)消息的方式进行通信,客户端发送请求(requests)到服务端,服务端发送响应(responses)到客户端。

请求消息格式

例子:

响应消息格式

例子:

为了标识特定资源需要特定的行为访问,HTTP协议定义了多种请求方法。这种特定资源是什么样的,是已有的数据,还有动态生成的?主要依赖于服务端实现。通常来说这种资源对应一个文件或者属于服务端的一个可执行输出。

HTTP/1.0规范定义三种请求方法:GET, POST, HEAD。HTTP/1.1规范又增加了五种:OPTIONS, PUT, DELETE, TRACE,CONNECT。

在规范中定义的这些请求方法是语义化的,并且是可依赖的。任何客户端都可以使用任何请求方法,服务端也可以配置成支持任何这些请求方法的组合。

实际上这些请求方法可以随意定义,没有数量限制,不过你自己定义出来的请求方法会被认为是不安全并且是非幂等的。

总结 :这些请求方法本质上没有区别,最终都是TCP请求,唯一的区别就是每个请求方法,使用的时候,规范规定的使用格式不同,原则上必须按照规范规定的格式使用,其实也可以违反规范使用,比如你可以使用GET方法请求数据,也可以使用GET方法提交数据,当然你可以用POST方法提交数据,也可以用POST方法获取数据。

做好前端开发必须对HTTP的相关知识有所了解,所以我创建了一个专题 前端必备HTTP技能 专门收集前端相关的HTTP知识,欢迎关注,投稿。

HTTP(超文本传输协议)是浏览器与服务端之间最主要的通信协议。这里将介绍http各版本解决的核心问题。

http最初的版本是http 0.9,如它的名字定义,主要是为了解决超文本(Html)内容传输问题

协议定义了客户端发起请求、服务端响应请求的通信模式。

随着浏览器和互联网的发展,单文本类型的传输已经无法满足通信的需求,浏览器希望可以通过http请求不同类型的文件,比如脚本、样式、图片、音视频等。

为了解决这个问题,出现了http 1.0,它主要是通过 增加头部设定 (即请求头和响应头)来解决不同类型文件的传输问题:

这也为后来实现很多功能奠定了基础,比如缓存、认证信息等,都是通过请求头和响应头来实现的。

虽然http1.0解决了不同类型文件的传输问题,但它还有很大的 局限性 ,就是它每次通信都要经过三个阶段:

存在的问题:

为了解决http 1.0的问题,增加了一个创建持久连接的方法。主要实现是当一个连接传输完成时,并不是马上进行关闭,而是继续复用它传输其他请求的数据,这个连接保持到浏览器或者服务器要求断开连接为止。

http是基于tcp来创建连接和断开连接,其过程分别是由 三次握手 四次挥手 实现的。

在tcp创建连接之前,是通过三次握手来确认双方有发送和接收的能力:

为什么是三次握手建立连接?

因为第1次握手让服务端知道客户端有发送的能力;第2次握手是为了让客户端知道服务端有接收和发送的能力;第3次是为了让服务端知道客户端有接收的能力。当通过3次握手后,双方才能确认对方都有发送和接收的能力,此时连接才能正式建立

当客户端和服务端断开连接时要发送四次数据,这个过程称之为四次挥手。

为什么是四次挥手?

因为在第二次服务端响应时,只是告诉客户端自己接收到了断开请求,并不能立即断开连接,而是要等服务端将所有请求都响应完毕后,才能发送响应告诉客户端自己准备好可以断开了。所以要经过四次挥手才能断开。

HTTP/1.1 虽然通过长连接减少了大量创建/断开连接造成的性能消耗,但由于它的并发能力受到限制,所以传输性能还有很大提升空间。

HTTP/2 中新增了一个二进制分帧的机制来提升传输效率。

HTTP/2 将默认不再使用 ASCII 编码传输,而是改为二进制数据。

当然 HTTP/2 也并非完美,考虑一种情况,如果客户端或服务端在通信时出现 数据包丢失 ,或者任何一方的 网络出现中断 ,那么 整个 TCP 连接就会暂停

HTTP/2 由于采用二进制分帧进行多路复用,通常只使用一个 TCP 连接进行传输,在丢包或网络中断的情况下后面的所有数据都被阻塞。

但对于 HTTP/1.1 来说,可以开启多个 TCP 连接,任何一个 TCP 出现问题都不会影响其他 TCP 连接,剩余的 TCP 连接还可以正常传输数据。 这种情况下 HTTP/2 的表现就不如 HTTP/1 了

针对数据丢包或网络中断的问题,http3将 TCP 改成 UDP,从而彻底解决了这个问题。

UDP 相对于 TCP 而言最大的 特点 传输数据时不需要建立连接,可以同时发送多个数据包 ,所以传输效率很高, 缺点 就是 没有确认机制来保证对方一定能收到数据

HTTP中文名称是超文本传输协议(英文:HyperText Transfer Protocol),HTTP是基于 TCP/IP 协议之上的应用层协议,HTTP是万维网数据通信的基础。

因此,在HTTP建立之前,需要先等客户端与服务端建立TCP连接。

协议,网络协议的简称,网络协议是通信计算机双方必须共同遵从的一组约定。如怎么样建立连接、怎么样互相识别等。只有遵守这个约定,计算机之间才能相互通信交流。它的三要素是:语法、语义、时序。

为了使数据在网络上从源到达目的,网路通信的参与方必须遵循相同的规则,这套规则称为协议(protocol),它最终体现在网络上传输的数据包的格式。

协议往往分为几个层次进行定义,分层定义是为了使某一层协议的改变不影响其他层次的协议。

备注:以上文字来源于百度百科

Wireshark是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换。

在学习HTTP协议的过程中,因为HTTP协议的是看不见摸不着的,这给学习带来一定的难度。因此有必要用Wireshark抓包工具抓取一个HTTP协议下来观察。

Wireshark官网地址: https://wireshark.en.softonic.com/

先看一下Wireshark的界面:

显而易见:Wireshark抓包界面中分为顶部的菜单栏、过滤栏、上、中、下五个部分;

HTTP请求体中包含三个部分: ① 请求行、② 请求头(Header)、③ 请求正文(Body)

概括为文字如下:

HTTP响应体中包含三个部分: ① 状态行、② 响应头(Header)、③ 响应正文(Body)

概括为文字如下:

看到这里,有的小伙伴可能会提出问题:

问:在上图中[响应头]与[响应正文]之间是什么数据呢?

答:这些数据是Wireshark为了辅助展示出的一些指标数据。实际上,在网络包中并没有这些数据,这里对比一下最下面的方块,看一下网络包中真正的数据。

问:在网络分层中, Hypertext Transfer Protocol 已经是网络模型中的应用层了,那为什么上图的抓包中,最下面还有一层: Line-base text data:text/plain(1 lines)

答:这个问题的答案其实和上一个问题的答案一致,这只是Wireshark为了展示的更加人性化,将数据抽离在了该层展示低而已,注意看最下面的红色框框,在Header结束之后就是两个CRLF,紧接着就是数据(hello world!)了。

在HTTP协议中,除了将数据放在一个包中一次性发出,还可以通过分包方式将一个大批数据分在多个数据包中进行传输。需要注意的是,分包传输使用的也是同一个Socket连接。

在Header中通过 Transfer-Encoding: chunked 进行指定,该KV与 Content-Length 只能同时出现一个。

需要注意的是:在HTTP1.0版本协议中不支持分包。在HTTP1.1之后开始支持分包。

HTTP协议如果不做特殊处理都是一种短连接,即为一次会话建立TCP/IP之后,客户端与服务端基于TCP/IP的连接之上通过HTTP协议完成会话后,连接也会被服务端断开。下一次的HTTP请求,还是需要为这个请求进行三次握手创建TCP连接,用完之后还需要四次挥手断开TCP连接,这大大减少了传输效率。

而KeepAlive的产生就是为了弥补上述的不足。

HTTP1.0版本中需要在Header中加入 Connection: keep-alive 来指定会话完毕之后不立即断开连接,而是有一定的复用时间。HTTP1.1版本中,默认开启该配置: Connection: keep-alive

需要注意的是:TCP协议中也有KeepAlive参数,但是与HTTP的KeepAlive还是有区别的;

首先需要了解的是,复用到底复用的是什么,看了上面的介绍,短连接中的每次请求都需要先进行TCP的连接导致TCP链路无法复用,因此这里的复用其实是针对TCP链路的复用。

可以配合连接池,如HttpClient就对长连接具有管理的功能,注意这里的管理肯定是针对长连接了,短连接压根就无法复用。

当TCP连接需要关闭时,只需要在Header头中添加 Connection: close 即可。

Tomcat9版本中默认KeepTimeout为20s,我也查看了一下SpringBoot对于Tomcat的配置,发现SpringBoot没有对Tomcat参数做调整,至少KeepTimeout用的就是Tomcat默认值。

那么在这样的情况下,KeepTimeout最终应该为20s才对,但是在抓包过程中却发现其值为60s.

抓包如下:

TODO

了解了HTTP协议的结构之后,解决粘包拆包的问题就迎刃而解了。

HTTP的请求与响应,对于请求行、请求头、响应行、响应头而言,都可以通过CRLF与空格作为流的边界进行读取。

对于请求正文与响应正文而言,他们的字节长度在Header中的 Content-Length 中定义,假若,Header中没有 Content-Length 属性,取而代之的是 Transfer-Encoding: chunked ,那么就读取每一个chunk的size,继而再读取size个byte,知道读取到last-chunk的size为0。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/33215.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-02-20
下一篇2023-02-20

发表评论

登录后才能评论

评论列表(0条)

    保存