HTTP(HyperText Transfer Protocol)超文本传输协议,它是用于从服务器传输超文本到本地浏览器的一种传输协议。
按照七层传输协议,HTTP位于应用层协议,在TCP协议之上。如下图所示
* 基于C/S模式,支持基本认证和安全认证
* 客户端请求简单
常用的请求方法GET、POST,只需要依据每种请求方法来传递对应的路径和请求体即可。
* 灵活
HTTP协议允许传输任意类型的数据对象,传输数据类型有Content-Type加以标记。常见的Content-Type类型如下所示:
* 无状态
无状态是指:协议对于事务处理没有记忆能力。如果后续的连接需要用到之前的信息,那么就必须重传之前的信息。
这种无状态响应就比较快。
为了解决这种无状态,就出现了Cookie和Session技术,用于记录当前请求的session信息。
3.HTTP请求方法类型HTTP请求依据具体的方法类型来区分。那么HTTP有哪些具体的方法类型呢,如下图所示
更具体的方法信息可以参考: HTTP请求方式中8种请求方法(简单介绍) - 诗里刻画的影子 - 博客园
4.HTTP工作流程上面介绍了HTTP协议是基于C/S架构的,客户端与服务端的交互流程图如下:
* 客户端通过TCP三次握手与服务端建立连接
* TCP建立连接成功后,客户端向服务端发送HTTP请求
* 服务端接收到客户端的HTTP请求后,返回响应结果到客户端
* 客户端通过TCP四次挥手,与服务端断开TCP连接
到这里,本次交互结束。
5.HTTP的持久连接与非持久连接通过4中的HTTP客户端与服务端交互过程,我们可以发现一个问题,如果每次交互都要创建连接、关闭连接,那么在大量数据交互的情况下,建连和关闭都会是一个极大的传输性能瓶颈。
那么可不可以在创建连接完成后,后续不断的复用该连接进行数据传输,等传输结束后,再关闭连接呢?
答案肯定是可以的,这就是HTTP的持久连接功能。
非持久连接:
上述交互描述中的,每个TCP连接只能用于传输一个请求信息和一个响应信息。一次请求响应结束后,就关闭当前TCP连接。
持久连接:
持久连接时指当服务端发出响应后,可以让TCP连接持续打开,同一个客户端服务器之间的连接的后续请求响应都可以通过这个连接持续发送。
针对持久连接,又可以分为流水线型和非流水线型的
类别功能非流水线型客户端只有收到前一个请求的响应后才发送下一个请求流水线型客户端可以一个接一个的发送对服务端的请求,服务端接收到这些请求后,也是一个接一的发送响应结果 6.HTTP协议版本HTTP协议经过不断的发展,便有了不同的版本,具体时间线如下
我们现在用的比较多的就是HTTP/1.1版本的。
具体区别如下(以下内容来自: HTTP协议各版本的区别,你知道吗?-51CTO.COM )
HTTP0.9
1991年发布, 没有header,功能非常简单,只支持GET。
HTTP1.0
1996年发布,明文传输安全性差,header特别大。它相对0.9有以下增强:
增加了header(使用元数据与数据解耦)
增加了status code,用于声明请求的结果。
content-type可以传输其它文件。
请求头增加了http/1.0版本号。
缺点:每请求一次资源就新建一次tcp连接
HTTP1.1
1997发布,是现在使用最广泛的版本。它相对1.0有以下增强:
可以设置keepalive让http重用tcp连接(请求必需串行发送)
支持pipeline传输,请求发出后可以继续发送请求
增加了HOST头,让服务端知道用户请求的是哪个域名
增加了type、language、encoding等header
2014年更新了内容:
增加了TLS支持,即https传输
支持四种模型:短连接,可重用tcp的长链接,服务端push模型(服务端主动将数据推送到客户端cache中),websocket模型
缺点:还是文本协议,客户端服务端都需要利用cpu解压缩
HTTP2
2015年发布,主要是提升安全性与性能。它相对1.1的增强有:
头部压缩(合并同时发出请求的相同部分)
二进制分帧传输,更方便头部只传输差异部分
流多路复用,同一服务下只需要用一个连接,节省了连接
服务器推送,一次客户端请求服务端可以多次响应。
可以在一个tcp连接中并发发送请求
缺点:基于tcp传输,会有队头阻塞问题(丢包停止窗口滑动),tcp会丢包重传。tcp握手延时长,协议僵化问题
7.http协议实战
以上介绍了那么多http协议的相关知识点,现在便通过chrome浏览器和wireshark来感受下http协议的具体内容。
为了最简单化,笔者自建一个HTTP服务(基于SpringBoot暴露一个http服务,代码非常简单)
@RestController
public class HelloController {
@GetMapping("/hello")
public String sayHello(@RequestParam("userName") String userName) {
return "hello " + userName;
}
}
7.1 Chrome浏览器访问该服务
http://localhost:8080/hello?userName=jack
# 结果如下:
hello jack
通过chrome浏览器查看本次请求,具体信息如下:
General:
Request URL: http://localhost:8080/hello?userName=jack
Request Method: GET
Status Code: 200
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin
Response Headers:
Connection: keep-alive
Content-Length: 10
Content-Type: text/html;charset=UTF-8
Date: Sat, 04 Jun 2022 02:57:01 GMT
Keep-Alive: timeout=60
Request Headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Host: localhost:8080
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36
Query String Parameters:
userName: jack
上述主要分为四块:通用请求头、响应头、请求头、请求体
有关于HTTP协议,最重要的基本就是请求头和响应头信息了,本文主要偏实战,所以笔者不再赘述这些内容。
有需要的可以参考:
7.2 wireshark抓包http服务同样访问上述HelloController提供的http接口,抓包如下:
No.222为请求体,具体内容如下:
发起一个GET请求,URI为:http://localhost:8080/hello?userName=jack
No.790为响应体,具体内容如下:
响应状态码为200,响应值为hello jack。与我们在chrome浏览器中看到的是一致的。
总结:HTTP协议的相关知识点还是非常多的,如果读者希望了解更多更权限的知识点,可以参考下