参考链接
What really happens when you navigate to a URL
请求资源类型
静态资源
如果请求的是静态资源,那么流量有可能到达 CDN 服务器,利用中间服务器作缓存
动态资源
如果请求的是动态资源,流量可能依次经过代理/网关、Web 服务器、应用服务器、数据库
DNS 解析过程
一条域名的DNS记录会在本地有两种缓存:浏览器缓存和操作系统(OS)缓存
host 文件存储
:
Windows 系统:C:\Windows\System32\drivers\etc
Linux 系统:/etc/named.conf
- 在浏览器中访问的时候,会优先访问 浏览器缓存,如果未命中则访问 OS缓存(host 文件),最后再访问DNS服务器 (一般是ISP提供)
- 浏览器向 本地 DNS 服务器 发起请求,采用 递归或者迭代查询 的方式依次向 根域名服务器、顶级域名服务器、权威域名服务器 发起查询请求,直至找到一个或一组 IP 地址,返回给浏览器
HTTP 请求过程
- DNS 解析拿到服务器 IP 地址后,浏览器再通过系统 调用 Socket 接口与服务器 443 端口进行通信
- 整个过程可以分解为建立连接、发送 HTTP 请求、返回 HTTP 响应、维持连接、释放连接五个部分
建立连接(三次握手)
- 在连接建立之前,
服务器
必须做好接受连接的准备,通过 调用 socket、bind、listen 和 accept 四个函数来完成 绑定公网 IP、监听 443 端口和接受请求 的任务 客户端
通过 socket 和 connect 两个函数 主动打开连接,给服务器发送带有 SYN 标志位 的分组,随机生成一个 初始序列号 x,以及附带 MSS(Maximum Segment Size,最大段大小)等额外信息服务器
必须 确认收到客户端的分组 ,发送带有 SYN+ACK 标志位的分组,随机生成一个 初始序列号 y,确认号为 x+1,以及附带 MSS 等额外信息。当一端收到另外一端的 MSS 值时,会根据两者的 MSS 取最小值来决定随后的 TCP 最大报文段大小客户端
确认收到服务器的分组,发送带有 ACK 标志位的分组,确认号为 y+1,从而建立 TCP 连接
发送 HTTP 请求
- 建立起安全的加密信道后,浏览器开始发送 HTTP 请求
- 请求报文 由 请求行、请求头、空行、实体(Get 请求没有)组成
- 请求头:由通用首部、请求首部、实体首部、扩展首部组成
- 通用首部:无论是请求报文还是响应报文都可以使用,比如 Date;
- 请求首部:只有在请求报文中才有意义,分为 Accept 首部、条件请求首部、安全请求首部和代理请求首部这四类
- 实体首部作用于实体内容,分为内容首部和缓存首部这两类
- 扩展首部表示用户自定义的首部,通过 X- 前缀来添加
- 注意:HTTP 请求头是不区分大小写的,它基于 ASCII 进行编码,而实体可以基于其它编码方式,由 Content-Type 决定
- 请求头:由通用首部、请求首部、实体首部、扩展首部组成
返回 HTTP 响应
- 服务器接受并处理完请求,返回 HTTP 响应
- 响应报文 格式基本等同于请求报文,由 响应行、响应头、空行、实体 组成
- 区别于请求头:响应头有自己的响应首部集,比如 Vary、Set-Cookie,其它的通用首部、实体首部、扩展首部则共用
- 此外,浏览器和服务器必须保证 HTTP 的传输顺序,各自维护的队列中请求/响应顺序必须一一对应,否则会出现乱序而出错的情况。
维持连接
- 完成一次 HTTP 请求后,服务器并不是马上断开与客户端的连接
- 在 HTTP/1.1 中,Connection: keep-alive 是默认启用的,表示 持久连接 ,以便处理不久后到来的新请求,无需重新建立连接而增加慢启动开销,提高网络的吞吐能力
断开连接(四次挥手)
- 服务器向客户端发送 Alert 报文,类型为 Close Notify,通知客户端不再发送数据,即将关闭连接,同样,这条报文也是经过加密处理的
服务器
通过调用 close 函数 主动关闭连接,向客户端发送带有 FIN 标志位的分组,序列号为 m客户端
确认收到该分组 ,向服务器发送带有 ACK 标志位的分组,确认号为 m+1客户端
发送完所有数据后,向服务器发送带有 FIN 标志位 的分组,序列号为 n服务器
确认收到该分组 ,向客户端发送带有 ACK 标志位的分组,序列号为 n+1客户端
收到确认分组后,立即进入 CLOSED 状态- 同时,
服务器
等待 2 个 MSL (Maximum Segment Lifetime,最大报文生存时间) 的时间后,进入 CLOSED 状态