在浏览器的某个支付页面发起一次完整的支付请求,网络协议的各个层级分别做了哪些事情?
1. 应用层
应用层简要理解做了哪些事情?
- 通过
DNS协议或者HTTPDNS协议得到目标应用的ip地址。 - 通过
HTTP协议或者HTTPS协议将业务应用请求封装出一个正常的http请求包。 - 浏览器将http请求包交给传输层处理(socket编程)。
2. 传输层
传输层简要理解做了哪些事情?
- 通过
TCP协议或UDP协议将http包封装出新的TCP包或者UDP包。 - TCP或者UDP协议在封装报文时写入源端口 + 目标端口。
- 浏览器将包交给操作系统的网络层
3. 网络层
网络层简要理解做了哪些事情?
- 通过
IP协议将TCP包或者UDP包封装出对应的IP包。 - IP协议会在封装报文时写入源IP地址 + 目标IP地址。
4. 数据链路层
数据链路层简要理解做了哪些事情?
-
通过
ARP协议拿到ip地址对应的网关地址(本地网关默认为:192.168.1.1)对应的mac地址(如00:1A:2B:3C:4D:5E)。 -
将本机的mac地址 + 网关的mac地址封装到mac包中,发送给网关。
-
网关内部维护了一张
路由表,可以识别到目标IP接下来应该前往哪个路由(路由协议OSPF、BGP)。 -
最后一个路由内部识别到目标ip是自己的网段内的,再次通过
ARP协议得到目标ip的mac地址,并通过此mac地址完成mac包的发送。 -
目标服务器收到mac包后,校验mac地址;通过后,取下mac头,交给网络层,校验IP;通过后,取下IP头,将TCP包或UDP包交给传输层,对每个收到的帧数据进行恢复确认;确认后,传输层通过端口号,将数据包交给对应的应用层进行数据解析处理。
6. 物理层
将Frame帧转换为比特流(电信号/光信号)进行传输。
5. 整体流程
Q&A
网络包的协议头在发送和接收时是怎么写入和剥离的?
发送时(内存 + 硬件)
- 内存缓冲区预留14 + 20 + 20个字节的位置给到mac头、tcp头、ip头。
- 内存缓存区中从55的位置开始向后填充数据,之后逐层向预留空间内写入头信息。
- 最后计算并准假FCS校验帧到缓冲区的尾部,此时一个完整的数据包就生成了。
帧0:分配 [ ]
↑head/data/tail
帧1:预留 [54预留 | ]
↑head ↑data/tail
0x1000 0x1036
帧2:加数据 [54预留 |100数据| ]
↑head ↑data ↑tail
0x100 0x1036 0x109A
帧3:加TCP头 [34预留 |20TCP |100数据| ]
↑head ↑data ↑tail
0x100 0x1022 0x109A
帧4:加IP头 [14预留 |20IP |20TCP |100数据| ]
↑head ↑data ↑tail
0x100 0x100E 0x109A
帧5:加以太头 [14以太 |20IP |20TCP |100数据| ]
↑head/data ↑tail
0x100 0x109A
帧6:网卡发送 [14以太 |20IP |20TCP |100数据| + 4FCS(帧校验序列) ]
↑head/data ↑tail
--------↑sk_buff范围------ ↑FCS在sk_buff外(硬件网卡添加)
head = 0x1000
预留54字节后:
data = 0x1000 + 0x36 = 0x1036 (54=0x36)
添加100字节数据后:
tail = 0x1036 + 0x64 = 0x109A (100=0x64)
len = 0x64 = 100
添加TCP头20字节:
data = 0x1036 - 0x14 = 0x1022 (20=0x14)
len = 100 + 20 = 120
添加IP头20字节:
data = 0x1022 - 0x14 = 0x100E
len = 120 + 20 = 140
添加以太网头14字节:
data = 0x100E - 0x0E = 0x1000 (14=0x0E) ← 回到head!
len = 140 + 14 = 154
接收时
帧0:网卡接收 [14以太|20IP|20TCP|100数据|4FCS] ← 网卡完整接收
帧1:硬件校验 [14以太|20IP|20TCP|100数据|4FCS] ← 校验CRC32
校验通过✅
帧2:剥离FCS [14以太 | 20IP| 20TCP| 100数据| ] ← 硬件移除FCS,放入sk_buff
↑head/data ↑tail
0x1000 0x109A
帧3:去以太头 [14以太 | 20IP| 20TCP| 100数据| ]
↑head ↑data ↑tail
0x1000 0x100E 0x109A
帧4:去IP头 [14以太 | 20IP |20TCP |100数据| ]
↑head ↑data ↑tail
0x1000 0x1022
帧5:去TCP头 [14以太 |20IP |20TCP | 100数据| ]
↑head ↑data ↑tail
0x1000 0x100E 0x109A
帧6:应用读取 [14以太 |20IP |20TCP |100数据| ]
↑head ↑data ↑tail
0x1000 0x1022 0x109A
应用读取100字节数据
为什么各个协议头放到头部而不是尾部?
网络设备经常处理"流":
收到开头几个字节就能开始处理
头部在前:收到14字节就知道是不是发给我的
头部在后:必须收到整个包才知道
192.168.1.1是什么?
默认网关(路由器)
您的设备配置:
IP地址: 192.168.1.100 (您的电脑/手机)
子网掩码: 255.255.255.0 (/24)
默认网关: 192.168.1.1 (路由器)
所有非本地流量 → 发送到 192.168.1.1 → 路由器 → 互联网
私有地址范围
192.168.0.0 - 192.168.255.255 (192.168.0.0/16)
├─ 192.168.0.0/24 (192.168.0.1 - 192.168.0.254)
├─ 192.168.1.0/24 (192.168.1.1 - 192.168.1.254) ← 最常用!
├─ 192.168.2.0/24
└─ ... 共256个这样的网段
为什么要用私有地址?
公有IP稀缺且昂贵:
一个家庭只需1个公有IP(路由器WAN口)
内部所有设备用私有IP(免费、可重复使用)
您的家庭网络: 互联网看到的:
├─ 手机: 192.168.1.101 │
├─ 电脑: 192.168.1.102 ├─ 都显示为 123.123.123.123
├─ 平板: 192.168.1.103 │ (您的路由器公有IP,但是标注用户代理是手机还是电脑等)
└─ 路由器WAN: 123.123.123.123
典型的网络拓扑
互联网
│
├─ 光猫/调制解调器
│ │
│ WAN口: 公有IP (如 123.123.123.123)
│
└─ 路由器 (192.168.1.1)
│
├─ 电脑: 192.168.1.100
├─ 手机: 192.168.1.101
├─ 电视: 192.168.1.102
└─ ... 最多253个设备
子网划分
192.168.1.0/24 网段:
网络地址: 192.168.1.0 (标识整个网络)
可用主机: 192.168.1.1 - 192.168.1.254
广播地址: 192.168.1.255 (发给该网段所有设备)
通常分配:
192.168.1.1 路由器/网关
192.168.1.2-99 静态分配设备(服务器、NAS等)
192.168.1.100-254 DHCP动态分配(手机、电脑等)
HTTPDNS协议是什么?
传输层的端口
通信过程示例(以访问网页为例)
a. 服务器端:Nginx Web服务器启动,主动绑定到 0.0.0.0:80 并监听。
b. 客户端:您在浏览器输入网址,浏览器请求内核建立一个TCP连接。
c. 源端口分配:您的操作系统从临时端口池(如 49152-65535)中挑选一个未被使用的端口(例如 59234)分配给这个浏览器标签页。
d. 封装与发送:内核构建TCP报文,设置:
- 源端口:
59234(客户端临时端口) - 目标端口:
80(服务器知名端口)
e. 服务器响应:服务器回包时,会将源端口和目标端口对调:
- 源端口:
80 - 目标端口:
59234
这样,双方的协议栈就能根据 “协议, 源IP, 源端口, 目标IP, 目标端口” 唯一标识一个通信连接或数据流。
ip地址为什么不在网络层再解析?
既然ip协议是在网络层,为什么要在应用层就用DNS服务解析出ip地址呢?如果网络层直接处理域名翻译,会出现以下情况:
- 每个数据包携带域名,头部臃肿
- 所有路由器需要解析DNS,性能暴跌
- DNS故障导致全网瘫痪
- 路由表需存储全球域名,内存爆炸
而现有在应用层直接处理的优势是:
- 应用层解析一次,缓存结果,多次使用
- 网络层专注快速转发,毫秒级路由
- 灵活性强:DNS记录可随时更新,网络层无感知
- 安全性好:中间设备看不到通信语义
为什么不能仅仅依靠IP寻址,还要有mac地址呢?
MAC地址:
- 固化:由网卡制造商烧录,理论上全球唯一,且通常终身不变。
- 扁平结构:没有内在的层次关系。
AA-BB-CC-DD-EE-FF和11-22-33-44-55-66之间看不出任何地理位置或网络归属的关联。 - 不适合路由:互联网上有数十亿设备,路由器无法维护一个包含所有MAC地址的、没有结构的“世界通讯录”来寻路。
IP地址:
- 动态分配:由网络管理员或DHCP服务器分配,可以随时改变(比如你换个Wi-Fi,IP就变了)。
- 层次化结构:像电话号码(国家码+区号+本地号)一样是分层的。例如
192.168.1.10,192.168.1.0/24表示一个子网。路由器只需要知道如何到达某个网络(比如18.0.0.0/8属于某公司),而不需要知道该网络内每一台具体设备。 - 完美适合路由:路由器之间通过路由协议(如BGP)交换网络路径信息,构建出一张高效的“互联网地图”,指导数据包在复杂的网络环境中跳转。
“最后一公里”问题:IP地址在局域网内无法直接定位
这是最直接的技术原因。假设在一个局域网内,你的电脑(IP: 192.168.1.100)想给同一Wi-Fi下的打印机(IP: 192.168.1.200)发送数据。
- 仅有IP地址时:你的电脑只知道打印机的“逻辑地址”(IP),但它无法直接在电波或网线上喊话:“IP是192.168.1.200的,请接收!” 因为网络硬件(网卡、交换机)只认MAC地址。它们是通过MAC地址来识别和转发数据的。
- 解决方案的悖论:你可能会想:“那就让交换机也学会IP地址啊!” 这实际上就是把交换机升级成路由器了。但路由器工作在网络层,其复杂度、成本和时延都比交换机(数据链路层设备)高得多。用路由器来处理局域网内部海量的、高速的通信(如文件共享、视频流),是极其低效和不经济的。