1.浏览器做的第一步工作是解析 URL
对 URL 进行解析,从而生成发送给 Web 服务器的请求信息
URL?
URL 实际上是请求服务器里的文件资源
当没有路径名时,就代表访问根目录下事先设置的默认文件,也就是 /index.html 或者 /default.html 这些文件
对 URL 进行解析之后,浏览器确定了 Web 服务器和文件名,接下来根据这些信息生成 HTTP 请求消息。
2.真实地址查询 —— DNS
通过浏览器解析 URL 并生成 HTTP 消息后,需要委托操作系统将消息发送给 Web 服务器。
但在发送之前,需要查询服务器域名对应的 IP 地址,因为委托操作系统发送消息时,必须提供通信对象的 IP 地址。
DNS 服务器:保存了 Web 服务器域名与 IP 的对应关系
DNS 中的域名都是用句点来分隔的,比如 www.server.com;越靠右的位置表示其层级越高;
域名最后还有一个点,比如 www.server.com.,这个最后的一个点代表根域名
域名的层级关系:
根 DNS 服务器(.)
顶级域 DNS 服务器(.com)
权威 DNS 服务器(server.com)
根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中:任何 DNS 服务器就都可以找到并访问根域 DNS 服务器
域名解析的工作流程:
1.客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器(也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址)。
2.本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器,根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。
3.根 DNS 收到来自本地 DNS 的请求后,把 .com 顶级域名服务器地址给你 本地 DNS 收到顶级域名服务器的地址后,发起请求给顶级域名服务器,顶级域名服务器把权威 DNS 服务器的地址给我们
4.本地 DNS 于是转向权威 DNS 服务器,权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。
5.本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。
那是不是每次解析域名都要经过那么多的步骤呢?
不是
浏览器会先看自身有没有对这个域名的缓存,如果有,就直接返回,如果没有,就去问操作系统,操作系统也会去看自己的缓存,如果有,就直接返回,如果没有,再去 hosts 文件看,也没有,才会去问「本地 DNS 服务器」。
3.协议栈
通过 DNS 获取到 IP 后,就可以把 HTTP 的传输工作交给操作系统中的协议栈
应用程序(浏览器)通过调用 Socket 库,来委托协议栈工作。
IP 中包括 ICMP 协议和 ARP 协议。
ICMP 用于告知网络包传送过程中产生的错误以及各种控制信息。
ARP 用于根据 IP 地址查询相应的以太网 MAC 地址
网卡驱动程序负责控制网卡硬件
最下面的网卡负责完成实际的收发操作,也就是对网线中的信号执行发送和接收操作
4.TCP
HTTP 是基于 TCP 协议传输的
TCP 报文头部的格式
序号:为了解决包乱序的问题
确认号:确认发出去对方是否有收到
状态位:
SYN 是发起一个连接
ACK 是回复
RST 是重新连接
FIN 是结束连接
TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。
窗口大小:TCP 要做流量控制,通信双方各声明一个窗口(缓存大小),标识自己当前能够的处理能力
拥塞控制:控制发送的速度
在 HTTP 传输数据之前,首先需要 TCP 建立连接,TCP 连接的建立,通常称为三次握手
「连接」,只是双方计算机里维护一个状态机
1.一开始,客户端和服务端都处于 CLOSED 状态。 先是服务端主动监听某个端口,处于 LISTEN 状态。
2.客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。
3.服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,之后处于 SYN-RCVD 状态。
4.客户端收到服务端发送的 SYN 和 ACK 之后,发送对 SYN 确认的 ACK,之后处于 ESTABLISHED 状态,因为它一发一收成功了。
5.服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。
所以三次握手目的是保证双方都有发送和接收的能力。
TCP 分割数据:
如果 HTTP 请求消息比较长,超过了 MSS 的长度,数据会被以 MSS 的长度为单位进行拆分,拆分出来的每一块数据都会被放进单独的网络包中。也就是在每个被拆分的数据加上 TCP 头信息,然后交给 IP 模块来发送数据。
TCP 协议里面会有两个端口:
一个是浏览器监听的端口(通常是随机生成的)
一个是 Web 服务器监听的端口(HTTP 默认端口号是 80, HTTPS 默认端口号是443)
在双方建立了连接后,TCP 报文中的数据部分就是存放 HTTP 头部 + 数据,组装好 TCP 报文之后,就需交给下面的网络层处理
网络包的报文如下图
5.IP
IP 协议里面需要有源地址 IP 和 目标地址 IP:
源地址IP,即是客户端输出的 IP 地址;
目标地址,即通过 DNS 域名解析得到的 Web 服务器 IP。
6.MAC
MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息
ARP 协议帮我们找到路由器的 MAC 地址:
1.ARP 协议会在以太网中以广播的形式,得到对方的 MAC 地址
2.在后续操作系统会把本次查询结果放到一块叫做 ARP 缓存的内存空间留着以后用
在发包时:
1.先查询 ARP 缓存,如果其中已经保存了对方的 MAC 地址,就不需要发送 ARP 查询,直接使用 ARP 缓存中的地址。
2.当 ARP 缓存中不存在对方 MAC 地址时,则发送 ARP 广播查询。
7.网卡(出口)
网络包只是存放在内存中的一串二进制数字信息,没有办法直接发送给对方
网卡:将数字信息转换为电信号,在网线上传输,这才是真正的数据发送过程
网卡驱动程序控制网卡
网卡驱动获取网络包之后,会将其复制到网卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列
- 起始帧分界符是一个用来表示包起始位置的标记
2.末尾的 FCS(帧校验序列)用来检查包传输过程是否有损坏
最后网卡会将包转为电信号,通过网线发送出去。
总结:服务器 与 客户端
1.数据包抵达服务器后,服务器会先扒开数据包的 MAC 头部,查看是否和服务器自己的 MAC 地址符合,符合就将包收起来。
2.接着继续扒开数据包的 IP 头,发现 IP 地址符合,根据 IP 头中协议项,知道自己上层是 TCP 协议。
3.于是,扒开 TCP 的头,里面有序列号,需要看一看这个序列包是不是我想要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。 TCP 头部里面还有端口号, HTTP 的服务器正在监听这个端口号。
4.于是,服务器自然就知道是 HTTP 进程想要这个包,于是就将包发给 HTTP 进程。
5.服务器的 HTTP 进程看到,原来这个请求是要访问一个页面,于是就把这个网页封装在 HTTP 响应报文里。
6.HTTP 响应报文也需要穿上 TCP、IP、MAC 头部,不过这次是源地址是服务器 IP 地址,目的地址是客户端 IP 地址。
7.穿好头部衣服后,从网卡出去,交由交换机转发到出城的路由器,路由器就把响应数据包发到了下一个路由器,就这样跳啊跳。
8.最后跳到了客户端的城门把守的路由器,路由器扒开 IP 头部发现是要找城内的人,于是又把包发给了城内的交换机,再由交换机转发到客户端。
9.客户端收到了服务器的响应数据包后,客户端开始扒皮,把收到的数据包的皮扒剩 HTTP 响应报文后,交给浏览器去渲染页面,一份特别的数据包,就这样显示出来了!
最后,客户端要离开了,向服务器发起了 TCP 四次挥手,至此双方的连接就断开了