HTTP 协议用于客户端和服务器端之间的通信,应用 HTTP 协议时,必定是一端担任客户端角色,另一端担任服务器端角色。
一、请求、响应报文
请求
包含了:请求方法、请求 URI、协议版本、请求首部字段(可选)和内容实体。
响应
包含了:协议版本、状态码(比如200)、用以解释状态码的原因短语、响应首部字段(可选)以及实体主体。
二、HTTP 是无状态的
1. 无状态
HTTP 是一种不保存状态,即无状态(stateless)协议,对于发送过的请求或响应都不做持久化处理。
使用 HTTP 协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。
这样的目的是更快地处理大量事务,确保协议的可伸缩性,特意把 HTTP 协议设 计成如此简单的。
不过,随着web的发展,因无状态而导致业务处理变得棘手的情况增多了。比如,用户登录到一家购物网站,即使他跳转到该站的其他页面后,也需要能继续保持登录状态。
HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能,于 是引入了 Cookie 技术。
2. Cookie
Cookie 技术通过在请求和响应报文中写入Cookie 信息来控制客户端的状态。
-
Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie。
-
当下次客户端再往该服务器 发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。
-
服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。
三、HTTP 方法
用于告知服务器意图。
-
GET:用来请求访问已被 URI 识别的资源。指定的资源经服务器 端解析后返回响应内容。
-
POST:POST 方法用来传输实体的主体
虽然用 GET 方法也可以传输实体的主体,但一般不用 GET 方法进行传输,而是用 POST 方法。
虽说 POST 的功能与 GET 很相似,但 POST 的主要目的并不是获取响应的主体内容。 -
PUT:用来传输文件。
但是,鉴于 HTTP/1.1 的 PUT 方法自身不带验证机制,任何人都可以上传文件 , 存在安全性问题,因此一般的 Web 网站不使用该方法。
若架构设计采用 REST(REpresentational State Transfer,表征状态转移)标准的同类 Web 网站,就可能会开放使用 PUT 方法。 -
HEAD:HEAD 方法和 GET 方法一样,只是不返回报文主体部分。用于确认 URI 的有效性及资源更新的日期时间等。
-
DELETE:DELETE 方法用来删除文件。
但是,HTTP/1.1 的 DELETE 方法本身和 PUT 方法一样不带验证机制,所以一般的 Web 网站也不使用 DELETE 方法。
当配合 Web 应用 程序的验证机制,或遵守 REST 标准时还是有可能会开放使用的。 -
OPTIONS:用来查询针对请求 URI 指定的资源支持的方法。
-
CONNECT:要求在与代理服务器通信时建立隧道,实现用隧道协 议进行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。
四、持久连接节省通信量
痛点
HTTP 协议的初始版本中,每进行一次 HTTP 通信就要断开一次 TCP 连接。
但是随着发展,浏览一个 HTML 页面可能会包含很多内容,比如有多张图片,每次的请求都会造成无谓的 TCP 连接建立和断开,增加通信量的开销。
持久连接
为解决上述 TCP 连接的问题,相出了持久连接的方法,也称为HTTP keep-alive 或 HTTP connection reuse。
只要任意一端 没有明确提出断开连接,则保持 TCP 连接状态。在建立 1 次 TCP 连接后进行多次请求和响应的交互。
四次挥手
这里补充一个知识点。
“挥手”即表示要说再见。在上图所示,断开TCP连接的时候看到有4次交互,这就是4次挥手。
这一过程由客户端或服务端任一方执行,图示里就是由服务器端主动发起的,客户端被动关闭:
- 第一次:服务器端发送一个 FIN,用来关闭客户端到服务器的数据传送。
- 第二次:客户端收到这个 FIN,它发回一个 ACK。
- 第三次:客户端关闭与服务器端的连接,发送一个 FIN 给服务器端。
- 第四次:服务器端发回 ACK 报文确认。
面试官爱追问:为什么连接的时候是三次握手,关闭的时候却是四次握手?
1)三次握手
当被动方收到主动方的 SYN 连接请求报文后,可以直接发送SYN+ACK报文。
其中 ACK 报文是用来应答的,SYN 报文是用来同步的。
2)四次挥手
首先,四次挥手是为了确保数据能够完整传输。
当被动方收到主动方的 FIN 报文通知时,它仅仅表示主动方没有数据再发送给被动方了。
但未必被动方所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,它可能还需要发送一些数据给主动方。
全部发送完成后再发送 FIN 报文给主动方,告诉主动方同意关闭连接。
所以这里的 ACK 报文和 FIN 报文多数情况下都是分开发送的。