网络:输入网址并回车之后的事
孤单小弟:HTTP
解析 URL
统一资源定位符:
URL
(Uniform Resource Locater)标识互联网中资源的位置(包含协议、服务器、资源路径等信息)。
如果省略资源路径名,则访问默认文件。
通常是
index.html
或default.html
生成 HTTP 请求信息
解析
URL
之后,浏览器确定了 Web 服务器和文件名。从而生成 HTTP 请求报文。
报文格式:
解析 URL 并生成 HTTP 请求信息后,需要委托操作系统发送消息。
发送之前,需要获取服务器域名对应的 IP 地址。
真实地址查询:DNS
域名服务器:
DNS
(Domain Name System)保存服务器域名与 IP 地址的映射关系。
域名层级关系
-
域名层级通过
.
划分,越靠右的层级越高(e.g.www.server.com
) -
域名最后还有一个
.
(通常省略),代表根域名(e.g.www.server.com.
) -
结构:
-
根域名服务器(.)
-
顶级域名服务器(.com)
-
权威/权限域名服务器(server.com)
-
本地域名服务器
-
域名解析流程
假设要解析的目标域名:
www.server.com
(下称目标域名)
-
客户端:向本地 DNS 发起请求,询问目标域名的 IP 地址。
-
本地 DNS:
- 收到客户端请求。
- 查缓存:如果缓存里的表格能找到目标域名,则直接返回 IP 地址。否则进行下一步。
- 请求根域名服务器:向根 DNS 发出请求,询问目标域名的 IP 地址。
-
根 DNS:
- 收到本地 DNS 请求。
- 发现后缀是 .com,说明目标域名归 .com 区域管理。
- 响应:将目标域名的顶级 DNS(.com)的 IP 地址响应给本地 DNS。
-
本地 DNS:
- 收到根 DNS 的响应。
- 向 .com 顶级 DNS 发起请求,询问目标域名的 IP 地址。
-
顶级 DNS:
- 收到本地 DNS 请求。
- 发现后缀是 server.com,说明目标域名归 server.com 区域管理。
- 响应:将目标域名的权威 DNS(server.com)的 IP 地址响应给本地 DNS。
-
本地 DNS:
- 收到顶级 DNS 的响应。
- 向 server.com 权威 DNS 发起请求,询问目标域名的 IP 地址。
-
权威 DNS:
- 收到本地 DNS 请求。
- 服务器查询目标域名对应的IP 地址,响应给本地 DNS。
-
本地 DNS:
- 收到权威 DNS 响应。
- 将 IP 地址返回客户端。
-
客户端:和目标建立连接。
缓存
缓存可以提高域名解析效率
- 浏览器、操作系统、DNS 服务器等都会保存域名解析结果。
- 各个环节都会检查自身有没有域名的缓存,有则直接返回,没有才进行下一步。
- 浏览器缓存
- 操作系统缓存
- hosts 文件
- 本地 DNS 缓存
指南好帮手:协议栈
-
应用程序:浏览器调用
Socket
库,委托协议栈工作。 -
协议栈:分为两部分,收到委托后执行工作。
TCP
和UDP
协议:接收应用层的委托,执行收发数据的操作。IP
协议:控制网络包收发操作。- 在互联网上传数据时,数据会被切分成一块块的网络包,由 IP 负责发送给对方。
- IP 还包括
ICMP
协议和ARP
协议。ICMP
:用于告知网络包传送过程中产生的错误以及各种控制信息。ARP
:根据 IP 地址查询相应的以太网 MAC 地址。
-
驱动程序:网卡驱动程序负责控制网卡硬件。
-
硬件:物理硬件网卡负责完成实际的收发操作(对网线中的信号执行发送和接收操作)。
可靠传输:TCP
HTTP 基于 TCP 协议传输
首部
-
源端口号、目标端口号:
- 浏览器监听端口:通常随机生成。
- 服务器监听端口:HTTP 默认
80
, HTTPS 默认443
。
-
序号:解决包乱序的问题。
-
确认号:解决丢包的问题。
- 确认发出去对方是否有收到。
- 没有收到就应该重新发送,直到送达。
-
状态位:维护连接状态
SYN
:发起连接ACK
:回复RST
:重新连接FIN
:结束连接
-
窗口大小:
-
流量控制:通信双方各声明一个窗口(缓存大小)代表自身当前的处理能力,避免传输的太快或太慢。
-
除了流量控制,TCP 还有拥塞控制。
-
建立连接:三握
HTTP 传输数据之前,需要建立 TCP 连接(aka. 三次握手)。
- 连接:双方计算机里维护一个状态机,是虚拟的连接。
- 三次握手:目的是保证双方都有发送和接收的能力。
客户端和服务端都处于 CLOSED
状态。服务端先主动监听某个端口,处于 LISTEN
状态。
-
客户端:
- 主动发起连接
SYN
- 之后处于
SYN-SENT
状态
- 主动发起连接
-
服务端:
- 收到客户端
SYN
- 返回
SYN
、对客户端的SYN
确认ACK
- 之后处于
SYN-RCVD
状态
- 收到客户端
-
客户端:
- 收到服务端
SYN
和ACK
- 对服务端
SYN
确认ACK
- 之后处于
ESTABLISHED
状态(因为一发一收成功)
- 收到服务端
-
服务端:
- 收到客户端的
ACK
- 之后处于
ESTABLISHED
状态(因为一发一收成功)
- 收到客户端的
查看 TCP 连接状态:Linux 的
netstat -napt
命令。
TCP 分割数据
-
场景:HTTP 请求消息超过了
MSS
的长度,TCP 需要把数据拆分后发送,而不是一次性发送所有数据。-
MTU
(最大传输单元):一个网络包的最大长度,以太网中一般为1500
字节。 -
MSS
(最大报文段长度):除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。
-
-
拆分流程:
-
以
MSS
为单位来拆分数据,拆分出来的每一块数据会放进单独的网络包。 -
i.e. 每个被拆分数据加上 TCP 首部信息,分别交给 IP 模块来发送数据。
-
TCP 报文生成
此时网络包如下图所示:
- TCP 报文 = TCP 首部 + TCP 数据
- TCP 数据 = HTTP 首部 + 数据
远程定位:IP
TCP 模块在执行连接、收发、断开等各阶段操作时,
需要委托 IP 模块,将数据封装成网络包发送给通信对象。
首部
-
协议:HTTP 基于 TCP 传输,则协议号为
06
(十六进制)代表使用 TCP 协议。 -
源 IP 地址:客户端输出的 IP 地址。
-
目标 IP 地址:通过 DNS 域名解析得到的服务器 IP 地址。
路由表
场景:客户端有多个网卡,存在多个 IP 地址。
需要根据路由表规则,判断哪个网卡作为源 IP 地址。
-
判断机制:
- 接收方 IP 地址和子网掩码(Genmask)进行与运算,结果与目标地址(Destination)相同的作为源 IP 地址。
- 对路由表的记录逐条判断,直到确定源 IP 地址。
-
查看当前系统的路由表:Linux 系统
route -n
命令。 -
默认网关:假如路由表中前面所有记录都不匹配,会使用最后一行的默认网关。。
- 目标地址和子网掩码:都是
0.0.0.0
- 网关:路由器的 IP 地址
- 目标地址和子网掩码:都是
示例:服务器的目标地址是
192.168.10.200
,客户端的路由表如上
-
匹配过程:
- 第一条:与运算结果
192.168.10.0
,与 Destination 不相等,匹配失败。 - 第二条:与运算结果
192.168.10.0
,与 Destination 相等,匹配成功。
- 第一条:与运算结果
-
确定源 IP 地址:网卡 eth1 的地址。
IP 报文生成
此时网络包如下图所示:
- IP 报文 = IP 首部 + IP 数据
- IP 数据 = TCP 报文 = TCP 首部 + TCP 数据
- TCP 数据 = HTTP 首部 + 数据
两点传输:MAC
首部
MAC 首部是以太网使用,MAC 地址用于两点之间的传输。
-
发送方 MAC 地址(源):在网卡生产时写入到 ROM,可以直接读取。
-
接收方 MAC 地址(目标):下一跳的 MAC 地址,可能是路由器也可能是目标服务器。
- 在路由表中找到相匹配的条目,
Gateway
列值就是接收方的 IP 地址。 - 通过 ARP 协议,获取 MAC 地址。
- 在路由表中找到相匹配的条目,
-
协议类型:在 TCP/IP 通信中,通常只有两种取值。
-
0800
: IP 协议 -
0806
: ARP 协议
-
ARP
广播
机制
-
ARP 协议在以太网中通过广播的形式,向所有设备询问 IP 地址对应的 MAC 地址。
-
其它设备收到 ARP 的广播后,检查 IP 地址是否一致,是则返回 MAC 地址。
缓存
操作系统会将 ARP 查询结果放到内存空间中(ARP 缓存),缓存几分钟。
-
查看 ARP 缓存内容:Linux 系统的
arp -a
命令。 -
完整 ARP 发包过程:
- 缓存:查询 ARP 缓存,如果其中已经保存了对方的 MAC 地址,就不需要发送 ARP 查询,直接使用 ARP 缓存中的地址。
- 广播:当 ARP 缓存中不存在对方 MAC 地址时,则发送 ARP 广播查询。
MAC 报文生成
此时网络包如下图所示:
- MAC 报文 = MAC 首部 + MAC 数据
- MAC 数据 = IP 报文 = IP 首部 + IP 数据
- IP 数据 = TCP 首部 + TCP 数据
- TCP 数据 = HTTP 首部 + 数据
出口:网卡
网络包是内存中的一串二进制数字信息,需要将转换为电信号才能在网线上传输。
负责执行这一操作的是网卡,要控制网卡还需要靠网卡驱动程序。
网卡驱动工作流程:获取网络包之后,将其复制到网卡内的缓存区,在其头尾添加内容。
-
头部:添加报头和起始帧分界符(标记包的起始位置)。
-
尾部:添加帧校验序列(FSC, Frame Check Sequence),用于检查包传输过程是否有损坏。
送别者: 交换机
- 交换机工作在 MAC 层,也称为二层网络设备。
- 交换机的设计是将网络包原样转发到目的地。
接收包
接收过程
- 电信号到达网线接口,交换机里的模块进行接收并将电信号转换为数字信号。
- 通过包末尾的
FCS
校验错误,如果没问题则放到缓冲区。 - 查询 MAC 地址表:判断地址表中是否有包的接收方 MAC 地址。
- 是:将数字信号发送到对应端口。
- 否:将包转发到除了源端口之外的所有端口上(当接收方地址是广播地址
FF:FF:FF:FF:FF:FF
,也进行该操作)。
Hint 1:网卡 vs 交换机
计算机的网卡具有 MAC 地址,交换机的端口没有。
对于收到的网络包,处理如下。
- 计算机网卡:核对接收方 MAC 地址,判断不是发给自己的则丢弃。
- 交换机端口:不核对接收方 MAC 地址,直接接收所有的包并存放到缓冲区。
Hint 2:MAC 地址表信息
包含信息
-
连接到交换机的设备 MAC 地址
-
设备连接在交换机的哪个端口
出境大门:路由器
路由器 vs 交换机
网络包经过交换机之后,
到达路由器,在此被转发到下一个路由器或目标设备。
路由器 | 交换机 | |
---|---|---|
设计基础 | 基于 IP | 基于以太网 |
aka. | 三层网络设备 (网络、数据链路、物理) |
二层网络设备 (数据链路、物理) |
端口情况 | 具有 MAC 地址和 IP 地址 | 不具有 MAC 地址 |
路由器基本原理
功能
- 具有 MAC 地址,可以作为以太网的发送方和接收方;
- 具有 IP 地址,此处的功能和计算机的网卡相同。
转发操作:当转发包时
- 接收包:路由器端口会接收发给自己的以太网包。
- 查表:查询路由表,确认转发目标。
- 转发:由相应的端口作为发送方,将以太网包发送出去。
接收包
- 电信号到达网线接口,路由器中的模块进行接收并将电信号转成数字信号。
- 通过包末尾的
FCS
校验错误,没问题则继续。 - 比较 MAC 首部的接收方 MAC 地址:对比自身 MAC 地址。
- 相同则放到接收缓冲区。
- 否则丢弃包。
查询路由表
判断机制:同上文 IP 的路由表
-
接收方 IP 地址和子网掩码(Genmask)进行与运算,结果与目标地址(Destination)相同的作为源 IP 地址。
-
默认网关:假如路由表中前面所有记录都不匹配,会使用最后一行的默认网关。
上图中的第二条记录会匹配,即目标地址 192.168.1.0
转发
生成 MAC 报文
- 接收方 MAC 地址:
- 确认接收方 IP 地址:查看路由表的 Gateway 列值。
- IP 地址:说明包尚未抵达终点,将包转发到该 IP 地址。
- 空:说明已抵达终点,将包转发到 IP 首部的接收方 IP 地址。
ARP
协议:查询 IP 地址对应的 MAC 地址。- 查缓存,有则返回。
- 发送 ARP 查询请求。
- 确认接收方 IP 地址:查看路由表的 Gateway 列值。
- 发送方 MAC 地址:填写输出端口的 MAC 地址。
- 协议字段:填写
0800
(十六进制)表示 IP 协议。
发出 MAC 报文
- 路由器将网络包发出,通过交换机到达下一个路由器。
- 重复以上步骤,经过层层转发到达目的地。
在网络包传输的过程中,
IP 地址始终不变,MAC 地址随着设备改变而改变。
扒皮:服务器 & 客户端
数据包抵达服务器后,服务器开始扒皮
- 检查 MAC 首部:比较自身的 MAC 地址,相同则继续。
- 检查 IP 首部:
- 比较自身的 IP 地址,相同则继续。
- 检查 IP 首部的协议项,知道传输层是 TCP 协议。
- 检查 TCP 首部:
- 序列号:确认序列包是不是想要的。是则放入缓存后返回 ACK,不是则丢弃。
- 端口号:HTTP 服务器正在监听这个端口号。
- 将包发送给相应的 HTTP 进程。
- HTTP 进程:收到 HTTP 请求,将请求想要的资源封装在 HTTP 响应报文。
后续
- 服务端:将 HTTP 响应报文发送给客户端(类似请求报文的过程,区别是源地址和目的地址互换)
- 客户端:类似服务端对 HTTP 请求报文的处理,扒皮,获得响应数据包。
- 断开 TCP 连接(aka. 四次挥手)