这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
先让我放一下我找到的一张 计算机网络体系结构分层(图片来源):
然后让我们来讲主题:
一、概括
一次完整的 http请求,经历了以下的流程:
- 对网址进行 DNS解析,找到服务器对应的 IP地址。
- 经过 三次握手 后,建立起 TCP连接。
- 客户端向服务端发送请求信息
- 客户端向服务端发送请求头信息
- 服务端接收到请求
- 服务端向客户端发送响应头信息
- 服务端向客户端发送响应信息
- 经过 四次挥手 服务端关闭 TCP连接,完成本次请求
二、详解
1. DNS 解析
上一篇文章也讲过了,DNS协议运行在UDP协议之上,使用端口号53。
进行DNS域名解析时,会经过以下流程:
- 从自身浏览器中查找缓存
- 找不到则从系统自身的缓存中查找
- 还是找不到的话,则尝试从 hosts文件里面去找
- 在前面三个过程都没获取到的情况下,就递归地去域名服务器去查找
解析后会记录到本地的缓存中一段时间,方便下一次使用。
2. 三次握手
所谓的三次握手,是指在拿到 IP地址后,客户端要和服务器建立起TCP连接,需要一共发三次包。
我理解的三次握手(简化版):
第一次握手:
- 客户端随机生成一个序列号发送给服务端,并等待回应。(客户端 -> 服务端)阿斯顿发撒法发射点发生。
第二次握手:
- 服务端接收到序列号后结合客户端的序列号也随机生成一个序列号发回给客户端,并等待客户端确定。(服务端 -> 客户端)
第三次握手:
- 客户端收到服务端的数据后,确定数据无误后并向服务端确认,服务端收到确认后,则成功建立连接,双方进入连接状态。(客户端 -> 服务端)
一般TCP连接的端口号为80。
3. 发送请求
客户端向服务端发送的请求可以拆分为三个部分:
(1) 请求行
用于描述请求方式、请求资源名称以及使用的HTTP协议的版本号
GET /index.html HTTP/1.1
复制代码
(2) 请求头
用于描述缓存信息、客户端身份信息、请求地址、环境信息等等
Referer: https://www.baidu.com
Cookie:gsScrollPos=; _ga=GA1.2.329038035.1465891024; _gat=1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
...
复制代码
(3) 消息体
我们使用的请求方式为 POST
、PUT
等方式时,通常需要向服务端传递数据,这些数据就存在消息体中(GET
请求的消息体在 url的 “?” 后面,不会放到这里),这个不是必须有的。
4. 响应信息
服务端向客户端回复的响应也可以拆分为三个部分:
(1) 状态码
用于表示服务器对本次请求的处理结果(状态)。
HTTP/1.1 200 OK
复制代码
常见的状态码有:
类别 | 原因短语 | |
---|---|---|
1XX | Informational(信息性状态码) | 接受的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
- 200:请求成功且成功返回
- 301:请求位置更新,返回新的地址且重新请求
- 400:无法解析请求内容
- 401:请求没通过http认证
- 403:请求的资源不允许访问
- 404:请求的资源没有找到或不存在
- 500:服务器出故障
(2) 响应头
用于描述服务端的基本信息等。
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html; charset=utf-8
Date:Fri, 24 Jun 2016 06:23:31 GMT
Server:nginx/1.9.12
Transfer-Encoding:chunked
复制代码
(3) 响应体
即服务器返回给客户端的请求数据,例如 HTML文本、图片、json等。
像请求信息和响应信息,都是可以在Chrome的开发者工具里的Network
里可以看到。
5. 四次挥手
与三次握手相对的就是四次挥手,作用也是相反的,一个用于建立TCP连接,一个用于断开TCP连接。
四次挥手的命名,也是因为在断开连接的过程中总共发了四次包。
我理解的四次挥手(简化版):
第一次挥手:
- 客户端发起挥手请求,把之前建立连接的序列号整理到请求报文中发给服务端,表明不再有请求并等待确认。(客户端 -> 服务端)
第二次挥手:
- 服务端收到挥手请求后,向客户端发送一段报文,表明确认挥手请求并同意关闭连接。(服务端 -> 客户端)
第三次挥手:
- 服务端向客户端发送报文,表明请求断开连接,并等待确认。(服务端 -> 客户端)
第四次挥手:
- 客户端收到来自服务端的断开连接请求后,表示确认并向服务端发送报文,服务端接受到客户端的确认后,变断开连接。客户端等待一段时间后没有收到回复,表示连接正常断开,变关闭连接。
若我们在请求头或响应头中添加以下信息:
Connection:keep-alive
复制代码
表明保持连接,则 TCP连接 在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽
三、总结
我这个http请求拆分的不是十分的详细,因为对于 TCP/IP 协议还不是特别的熟悉,等什么时候有时间了去详细的做一次了解。
有什么问题希望大家可以在评论区指出,我及时纠正。
新人上路,还请多多包含。
我是MoonLight,一个初出茅庐的小前端。