分层模型和应用协议
约 5995 字大约 20 分钟
2025-10-17
分层模型
分层的意义
当遇到一个复杂问题的时候,可以使用分层的思想把问题简单化
比如,你有半杯82年的可乐,想分享给你的朋友王富贵,但你们已经10年没有联系了。要完成这件事,你可能要考虑:
我用什么装可乐?
可能的方案:塑料瓶、玻璃瓶、煤气罐
怎么保证可乐始终处于低温?
可能的方案:保温杯、小冰箱、冰盒
如何保证可乐不被运输的人偷喝?
可能的方案:封条、在上面写「毒药」
如何获取王富贵的地址?
可能的方案:报案失踪、联系私人侦探、联系物流公司的朋友
如何运输?
可能的方案:自行车、汽车、火车、高铁、飞机、火箭
这就形成了一个分层结构

从常理出发,我们可以得出以下结论:
- 每层相对独立,只需解决自己的问题
- 每层无须考虑上层的交付,仅需把自己的结果交给下层即可
- 每层有多种方案可供选择,选择不同的方案不会对上下层造成影响
- 每一层会在上一层的基础上增加一些额外信息
五层网络模型
网络要解决的问题是:两个程序之间如何交换数据。
这是一个非常复杂的问题,因为两个程序有可能出现在不同的设备上。
面对复杂的问题,可以使用分层的方式来简化。
经过不断的演化,网络最终形成了五层模型:

MAC
MAC(Media Access Control)地址 是 网卡(Network Interface Card, NIC) 的硬件地址。
它相当于计算机在 局域网(LAN) 中的「身份证号码」。
每一张网卡(有线、无线都一样)都有一个全球唯一的标识,比如:
E4-B3-18-9A-7C-11或者:
e4:b3:18:9a:7c:11一共 6 个字节(48 位);
前 3 个字节(厂商号)由 IEEE 分配给厂商;
后 3 个字节(设备号)由厂商自己分配;
所以全球范围内几乎不会重复。
比如:
| 前缀 | 厂商 |
|---|---|
| 00:1A:2B | Intel |
| 3C:5A:B4 | Apple |
| 70:85:C2 | Huawei |
一个局域网的通信过程
假设现在你有一个小型局域网:
[PC1]──┐
│
[PC2]───┤───[交换机]───[路由器]───Internet
│
[PC3]──┘1️⃣ PC1 想发消息给 PC2(同一网段)
- PC1 想要访问 PC2 的 IP 地址(比如 192.168.1.5);
- 它知道自己的 IP,但不知道对方的 MAC 地址;
- 于是它会发送一个 ARP 请求(广播包):
目标MAC:FF:FF:FF:FF:FF:FF ← 广播地址
发送者MAC:E4:B3:18:9A:7C:11
内容:谁是 192.168.1.5?请告诉我你的 MAC!2️⃣ 所有设备都收到广播包
交换机会把广播包发给所有端口;
每台电脑都收到,但只有 IP=192.168.1.5 的 PC2 会回应:
我是 192.168.1.5,我的 MAC 是 3C:5A:B4:1E:22:093️⃣ 通信建立
PC1 现在在自己的 ARP 缓存表 里保存了这条映射:
192.168.1.5 -> 3C:5A:B4:1E:22:09之后发数据帧时,就直接用这个 MAC 地址,不再广播。
你可以把 MAC 地址理解为:
| 比喻 | 说明 |
|---|---|
| 身份证号码 | 每张网卡一个,全世界唯一(理论上) |
| 快递收件人姓名 | 在同一个小区(局域网)里,靠名字(MAC)识别 |
| 邮递员送信时的门牌号 | IP 是「小区名」,MAC 是「门牌号」 |
| 计算机的“指纹” | 由厂商刻在网卡里,硬件级别的标识 |
MAC 地址,原则上:每块网卡出厂时写死在芯片(EEPROM)中,称为 烧录地址(burn-in address),理论上唯一、永久不变。
但实际上:你完全可以 改 掉它,也叫 MAC spoofing(伪装)。
在 Linux 改:
sudo ip link set dev eth0 address 00:11:22:33:44:55在 Windows 改:
设备管理器 → 网卡 → 高级 → Network Address → 填写新值
修改后系统层会 覆盖 硬件 MAC,但实际上网卡 EEPROM 中原始值没变。
比喻:
- 出厂 MAC 是“出生时的指纹”;
- 修改后的 MAC 是“戴上了指纹手套”,别人看到的就不一样了,但你原来的指纹还在。
广播、单播、多播的区别
| 通信方式 | MAC 目标地址 | 意义 |
|---|---|---|
| 广播 | FF:FF:FF:FF:FF:FF | 发给同一局域网内所有设备(如 ARP 请求) |
| 单播 | 某一台设备的 MAC | 发给特定设备(如 PC1 -> PC2) |
| 多播 | 01:00:5E:xx:xx:xx | 发给特定组的设备(如视频会议) |
交换机如何“记住”MAC
交换机会维护一张 MAC 地址表(CAM 表):
| MAC 地址 | 端口号 |
|---|---|
| E4:B3:18:9A:7C:11 | Port 1 |
| 3C:5A:B4:1E:22:09 | Port 2 |
这样当 PC1 向 PC2 发送数据时,交换机直接查表,只发给对应端口,而不是全网广播,提高效率。
TCP / UDP
互联网通信分为几层(OSI 七层或 TCP/IP 四层模型):
| 层级 | 名称 | 举例 |
|---|---|---|
| 应用层 | HTTP、FTP、DNS | 浏览网页、传文件 |
| 传输层 | TCP、UDP | 数据的可靠传输 |
| 网络层 | IP | 负责路由、寻址(找哪台电脑) |
| 链路层 | MAC、ARP | 物理连接(找哪块网卡) |
简单理解:
- IP 解决“去哪台电脑”
- TCP/UDP 解决“怎么传数据”
- MAC 解决“怎么在局域网找到它”
TCP 与 UDP 的基本区别
| 特性 | TCP | UDP |
|---|---|---|
| 全称 | Transmission Control Protocol | User Datagram Protocol |
| 是否面向连接 | ✅ 是(要建立连接) | ❌ 否(直接发) |
| 是否可靠 | ✅ 有确认、重传 | ❌ 不保证到达 |
| 数据有序性 | ✅ 有 | ❌ 无 |
| 速度 | 慢 | 快 |
| 报文大小 | 理论上无限(分片后重组) | 一般 < 64KB |
| 适用场景 | Web、文件、邮件 | 视频通话、游戏、广播、DNS |
| 是否流式 | ✅ 是 | ❌ 否(一次一包) |
TCP 的工作原理(有“握手”和“挥手”)
TCP 是一个“有感情”的协议,通信前要“握手”,通信后要“挥手”:
三次握手(建立连接)
客户端 -> 服务端:SYN=1(我要连接你)
服务端 -> 客户端:SYN=1, ACK=1(我同意)
客户端 -> 服务端:ACK=1(确认)建立连接,双方知道对方已准备好通信。
像打电话:
- A 拨号说“喂,听得到吗?”
- B 回应“听得到,你呢?”
- A 回应“我也听得到,开始聊吧。”
四次挥手(断开连接)
客户端:FIN=1(我要挂了)
服务端:ACK=1(知道了)
服务端:FIN=1(我也要挂了)
客户端:ACK=1(确认)双方都确认数据传输结束,连接关闭。
比喻:挂电话时要双方都说“再见”,确保都听清楚再断线。
TCP 的可靠机制:TCP 用了很多手段来确保“数据不丢、不重、不乱”:
| 机制 | 功能 |
|---|---|
| 序列号(Sequence Number) | 数据包编号,防止乱序 |
| 确认应答(ACK) | 收到数据要回个确认 |
| 超时重传(Timeout Retransmission) | 没收到确认就重发 |
| 滑动窗口(Flow Control) | 控制发送速率,避免拥塞 |
| 拥塞控制(Congestion Control) | 避免网络堵塞 |
UDP 的工作原理(无连接、轻量级)
UDP 就是个“甩手掌柜”:
- 不建立连接;
- 直接把数据塞给 IP 层;
- 不关心是否送达;
- 不关心顺序。
UDP 报文结构:
| 源端口 | 目标端口 | 长度 | 校验和 | 数据内容 |没有握手,也没有重传。
比喻:
- TCP 像快递:收发前签合同、每个包有编号、丢了补发;
- UDP 像广播电台:直接喊话,听到算你运气好。
TCP 与 UDP 的典型应用场景
| 应用 | 协议 | 原因 |
|---|---|---|
| HTTP / HTTPS(网页) | TCP | 必须可靠、完整 |
| FTP(文件传输) | TCP | 文件不能少一字节 |
| SSH(远程登录) | TCP | 必须顺序正确 |
| DNS(域名解析) | UDP | 一问一答、快 |
| 视频通话 / 直播 | UDP | 即使掉一帧也要快 |
| 网络游戏 | UDP | 延迟更敏感,容忍少量丢包 |
| 局域网广播 | UDP | 一发多收,不需确认 |
比喻总结
| 比喻 | TCP | UDP |
|---|---|---|
| 类比 | 打电话 | 寄明信片 / 广播喊话 |
| 建立连接 | 先打招呼再说话 | 直接喊话 |
| 可靠性 | 确认每句话都听到 | 不管听没听到 |
| 顺序性 | 有编号 | 无编号 |
| 延迟 | 较高 | 极低 |
| 应用 | 网页、文件、SSH | 语音、视频、游戏 |
简单例子
你访问网站 https://example.com:
- 你的浏览器先通过 DNS(UDP) 问:“example.com 的 IP 是多少?”
- DNS 服务器返回 IP。
- 浏览器通过 TCP 三次握手 连接目标服务器的 443 端口。
- 双方交换 HTTPS 数据(基于 TCP)。
- 网页加载完,四次挥手断开连接。
所以一次网页加载,其实 TCP 和 UDP 都有登场。
数据的传输

应用把数据交给 传输层(TCP/UDP) → 传输层分段并加头 → 交给 网络层(IP) 加 IP 头 → 交给 链路层(Ethernet) 加 MAC 头变成帧 → 网卡 把帧变为电/光信号发出去 → 中间设备(交换机/路由器)按照 MAC/IP 转发 → 目标网卡接收信号,驱动/内核做解封装,一层层上交到目标应用。
简化的例子(完整头部栈)
应用:HTTP 请求(例如 GET /) 传输层:TCP(源端口 54321 -> 目标端口 80) 网络层:IPv4(源 IP 10.0.0.2 -> 目标 IP 93.184.216.34) 链路层:Ethernet(源 MAC aa:aa:aa:aa:aa:aa -> 目标 MAC bb:bb:bb:bb:bb:bb)
最终发送的是一帧(Frame),内部封装结构大致是:
Ethernet Header | IP Header | TCP Header | HTTP Payload逐步深剖(发送端,从上到下)
起点:应用层(在用户空间)
- 位置:用户进程(浏览器、curl、你的程序),用户空间(user space)。
- 操作:
- 通过 socket API(例如
send()/write())将数据提交给传输层(通常内核的 socket 实现)。 - 应用“只关心”要发送的字节流或消息,不关心分段、重传、路由细节。
- 通过 socket API(例如
- 职责:构建应用数据(HTTP 请求、视频帧、DNS 查询),并选择使用 TCP 还是 UDP(通过 socket 类型/端口)。
传输层(内核的 TCP/UDP 实现)
- 位置:操作系统内核网络栈(kernel space)。
- 操作(以 TCP 为例):
- 接收应用的数据,做分段(segmentation):把大数据分成不超过 MSS(最大报文段大小)的 TCP 段。
- 为每个段添加 TCP 头(序列号、ACK、窗口大小、标志位、校验和、源/目的端口等)。
- 管理 TCP 状态机(SYN/ESTABLISHED/FIN 等)、重传队列、确认处理、拥塞控制(慢启动、拥塞避免、快重传等)。
- 维护发送缓冲区(如果拥塞/对端窗口小,可能阻塞或缓冲数据)。
- 输出:带 TCP 头的数据块交给内核的 IP 层。
网络层(IP 层,内核)
- 位置:内核(routing 子系统)。
- 操作:
- 为每个 TCP 段添加 IP 头(源/目标 IP、TTL、协议字段、分片字段、校验和等)。
- 根据路由表决定下一跳(直接在同一网段就直接到目标 MAC,否则发给默认网关)。
- 可能对大包进行 IP 分片(当包比下层 MTU 大时),但现代网络更常见的是在传输层进行分段/路径 MTU 发现(PMTU)。
- 输出:IP 数据报(包含 TCP 段)交给数据链路层(下一跳的 MAC 地址)。
数据链路层(Ethernet,内核 + 驱动)
- 位置:内核 + 网卡驱动(device driver)。
- 操作:
- 查 ARP 缓存:将目的 IP 映射为目的 MAC(如果没有,发 ARP 广播请求来询问谁是该 IP)。
- 构造 Ethernet 帧:在 IP 前面加上以太网帧头(目标 MAC、源 MAC、EtherType)以及帧尾(FCS,帧校验序列—通常由网卡硬件计算)。
- 如果启用了 VLAN/MPLS 等,也会在这里插入相应头。
- 如果帧大小小于最小帧长,会进行填充。
- 输出:帧交给网卡设备(驱动通过 DMA 把内存中的帧传给网卡)。
网卡/PHY(硬件)
- 位置:网卡(NIC)和物理层(PHY)。
- 操作:
- 驱动告诉 NIC 的发送队列(ring buffer)去发送这个帧;通常通过 DMA 把帧数据放入网卡内存;
- NIC 执行校验(如 FCS)、可能做 硬件卸载(checksum offload、TCP segmentation offload),并把数据变换成电信号/光信号;
- 将信号通过介质(以太网线、Wi-Fi 天线)发送出去。
- 注意:现代 NIC 可以做很多“加速”工作(校验、分段、时间戳),减少 CPU 负担。
在网络中间:交换机 / 路由器 / NAT / 防火墙(转发/修改发生地)
交换机(Layer 2)
- 位置:网络设备(物理交换机或虚拟交换机)。
- 操作:
- 读取 Ethernet 帧的目标 MAC;
- 从 CAM 表(MAC 表)查找目标 MAC 所在端口并单播转发;如果未知,则洪泛(广播到所有端口);
- 职责:局域网内高效转发,不看 IP。
路由器(Layer 3)
- 位置:路由器或三层交换设备,甚至 “家庭路由器”。
- 操作:
- 根据 IP 头的目的地址查路由表,决定下一跳;
- 可能会 修改 MAC 头(替换为下一跳的 MAC)、调整 TTL(减 1)、重新计算 IP 校验和;
- 如果遇到 NAT(私网 ↔ 公网),会修改源/目的 IP/端口并维护 NAT 映射表(这是状态化的)。
- 职责:跨网段转发,做路由选择,并处理 NAT/防火墙规则(可能阻止或修改流量)。
目标端:接收端的逆向步骤(下到上)
网卡接收帧(硬件)
- 位置:目标设备的 NIC。
- 操作:
- 接收电/光信号并恢复成帧;
- 做 FCS 校验,若校验失败就丢弃帧;
- 将帧通过 DMA 放入内存接收环(rx ring),并发起中断或使用 NAPI(Linux 的零拷贝/批量接收优化)通知内核驱动。
链路层解封装(内核/驱动)
- 位置:内核驱动 + 网络栈。
- 操作:
- 驱动把帧交给内核网络栈;
- 检查目标 MAC 是否本机(或广播 / 多播),若不是则丢弃;
- 去掉 Ethernet 头,交给 IP 层处理;
- 如果有 VLAN 标签,先处理 VLAN。
网络层(IP)解封装
- 位置:内核。
- 操作:
- 检查 IP 头(版本、校验和、TTL、目的地址是否是本机);
- 若目标是本机,解开 IP 包,把里面数据交给相应的传输层(通过 protocol 字段判断是 TCP/UDP/ICMP 等);
- 若分片,进行分片重组(如果分片被使用);若 TTL 到 0,丢弃并可发 ICMP 超时。
- 注意:如果到达的是路由器而非最终目的地,路由器会继续转发而不是上交给传输层。
传输层(TCP/UDP)解封装
- 位置:内核。
- 操作(TCP):
- 去掉 TCP 头,检查校验和;
- 根据端口号找到对应的 socket(属于某个用户进程);
- 处理序列号、重传、乱序缓存、确认(内核会向发送方发送 ACK);
- 将数据复制到目标进程的接收缓冲区(或使用零拷贝技术减少复制)。
- 输出:当应用调用
recv()/read()时,内核把数据从 socket 缓冲区返回给用户进程。
应用层(用户空间)
- 位置:目标进程。
- 操作:应用读取数据并处理(渲染网页、播放音频、保存文件等)。
抽象与封装
每一层只“认识”自己的头/尾
封装原则:每一层只添加/移除自己负责的头信息,并只关注“向上层传输的数据何去何从”或“向下层如何传输”。
例如:IP 层不知道 HTTP 的具体内容;应用层不知道 MAC 是什么。
抽象边界:应用通过 socket(系统调用)与传输层交互;传输层与网络层在内核内部接口交互;链路层最终和硬件交互。
网络模型

OSI 七层模型 是最早提出的一个理论标准模型;
TCP/IP 模型 是根据实际互联网协议栈实现抽象出来的;
五层模型 则是教学简化版,用来更好地理解 TCP/IP 的分层通信。
OSI 七层模型
OSI(Open Systems Interconnection)模型,是国际标准化组织(ISO)在 1984 年提出的,目标是让不同系统之间的通信有统一规范。
七层结构(从下到上)
| 层级 | 名称 | 功能概述 | 举例 |
|---|---|---|---|
| 7️⃣ | 应用层 (Application) | 为用户提供网络服务 | HTTP、FTP、SMTP、DNS |
| 6️⃣ | 表示层 (Presentation) | 数据格式转换、加密、压缩 | SSL/TLS、JPEG、MP3 |
| 5️⃣ | 会话层 (Session) | 维护会话、建立和管理连接 | NetBIOS、RPC |
| 4️⃣ | 传输层 (Transport) | 提供端到端的可靠传输 | TCP、UDP |
| 3️⃣ | 网络层 (Network) | 路由选择、逻辑寻址 | IP、ICMP |
| 2️⃣ | 数据链路层 (Data Link) | MAC 地址寻址、帧传输 | Ethernet、PPP |
| 1️⃣ | 物理层 (Physical) | 比特流传输、电信号 | 网线、电缆、光纤、Wi-Fi 信号 |
特点
- 理论非常完整;
- 各层职责非常明确;
- 但实际实现中,太理想化,很多层(尤其 5~7 层)在现实协议中是混在一起的。
TCP/IP 四层模型
TCP/IP 模型是基于 实际互联网协议栈的实现 总结出来的,它是 OSI 的简化和实用版本,现在几乎所有网络通信都遵循它。
四层结构
| 层级 | 名称 | 对应 OSI 层 | 功能 | 示例协议 |
|---|---|---|---|---|
| 4️⃣ | 应用层 | 应用 + 表示 + 会话 | 为用户提供服务 | HTTP、DNS、SMTP、SSH |
| 3️⃣ | 传输层 | 传输层 | 端到端通信 | TCP、UDP |
| 2️⃣ | 网络层 | 网络层 | IP 地址、路由 | IP、ICMP、ARP |
| 1️⃣ | 网络接口层(链路层) | 数据链路 + 物理层 | 数据帧传输 | Ethernet、Wi-Fi、PPP |
特点
- 实际互联网协议就是按它实现的;
- 逻辑清晰;
- 一些层被合并了(如 OSI 的上三层统一为“应用层”)。
TCP/IP 五层模型
在计算机网络课程中,常用“五层模型”作为讲解工具,它介于 OSI 七层 和 TCP/IP 四层 之间,更清晰地展示每层作用。
五层结构
| 层级 | 名称 | 职责 | 举例协议 |
|---|---|---|---|
| 5️⃣ | 应用层 | 直接为应用提供服务 | HTTP、DNS、FTP |
| 4️⃣ | 传输层 | 进程间通信,可靠性保证 | TCP、UDP |
| 3️⃣ | 网络层 | 选路、寻址 | IP、ICMP |
| 2️⃣ | 数据链路层 | MAC 地址通信、成帧 | Ethernet、Wi-Fi |
| 1️⃣ | 物理层 | 比特流传输 | RJ45、光纤、射频信号 |
特点
- 比 TCP/IP 四层模型更细(拆分了最底层);
- 更容易讲解封装、解封装过程;
- 教科书(如谢希仁《计算机网络》)最常用这个。
应用层协议
URL

URL(Uniform Resource Locator)就是统一资源定位符,本质上就是告诉浏览器或程序去哪拿资源,以及用什么协议去访问它。

URL 格式:
协议://域名[:端口]/路径[?查询参数][#锚点]示例:
https://www.example.com:443/path/file.html?query=1#tophttps → 协议
www.example.com → 域名/服务器地址
443 → 端口(可省略,浏览器会默认端口)
/path/file.html → 路径
?query=1 → 查询参数(GET 参数)
#top → 页面锚点(前端用)
常见 URL 协议
HTTP/HTTPS
- HTTP(HyperText Transfer Protocol)
- 无加密,用于普通网页或 API 请求
- 默认端口 80
- HTTPS(HTTP over TLS/SSL)
- 加密版 HTTP,保证数据安全
- 默认端口 443
- 使用场景:网页访问、API 请求、RESTful 通信
FTP / SFTP
- FTP(File Transfer Protocol)
- 用于文件上传/下载
- 默认端口 21
- SFTP(SSH File Transfer Protocol)
- 基于 SSH 加密的文件传输
- 默认端口 22
- 使用场景:服务器文件管理、部署
邮件协议
- SMTP(Simple Mail Transfer Protocol)
- 发送邮件
- 默认端口 25/587
- POP3 / IMAP
- 收邮件
- POP3 默认 110,IMAP 默认 143
其他常见协议
- file:// → 访问本地文件
- data:// → 内联数据,例如小图片 base64
- ws:// / wss:// → WebSocket(实时通信)
- ws 默认 80,wss 默认 443
- tel:// → 电话链接
- mailto:// → 邮件链接
端口和协议
| 协议 | 默认端口 | 是否加密 |
|---|---|---|
| HTTP | 80 | ❌ |
| HTTPS | 443 | ✅ |
- 当你在浏览器输入
http://example.com→ 浏览器默认去 80 端口 - 输入
https://example.com→ 默认去 443 端口 - 也可以显式写端口,例如:
https://example.com:8443→ 浏览器就去 8443 端口
为什么 nginx、Caddy 都监听 80 和 443
- 80 是 HTTP:
- 用于普通未加密网页或从 HTTP 重定向到 HTTPS
- 用户不写端口号时自动访问 80
- 443 是 HTTPS:
- 用于加密访问
- 浏览器默认 HTTPS 就会访问 443
- 监听端口 = 服务端入口:
- 服务器进程(nginx、Caddy)在操作系统上绑定这些端口
- 这样客户端请求就可以打到你的应用层(HTTP/HTTPS 协议处理)
总结:不写端口号 = 用协议默认端口,正好打到服务器监听的入口,服务器再把请求交给应用层处理。
精简:
当你在浏览器输入一个 URL(例如 https://example.com)时,URL 的协议(HTTP 或 HTTPS)决定了客户端要使用哪种应用层协议,同时也决定默认端口(HTTP 默认 80,HTTPS 默认 443)。
浏览器会把请求发送到域名解析出的服务器 IP 和对应端口,服务器(如 nginx 或 Caddy)在这些端口上监听,接收请求后再交给应用层处理。也就是说,不写端口号时,浏览器自动用协议默认端口,正好对应服务器的监听入口,从而完成整个应用层的数据传输流程。
HTTP
HTTP(HyperText Transfer Protocol)是应用层协议,负责客户端和服务器之间的请求与响应。它只定义数据怎么传,不负责数据怎么送(传输任务由 TCP/IP 完成)。
该协议规定了两个方面的内容:
- 传递消息的模式
- 传递消息的格式

客户端(浏览器/APP) ---- 请求(Request) ----> 服务器
客户端(浏览器/APP) <---- 响应(Response) ---- 服务器HTTP使用了一种极为简单的消息传递模式,「请求-响应」模式
发起请求的称之为客户端,接收请求并完成响应的称之为服务器。
「请求-响应」完成后,一次交互结束。
传递消息的格式

HTTP的消息格式是一种纯文本的格式,文本分为三个部分:
请求行
请求头
请求体注意:请求体和请求头中间空了一行
实践
有非常多的工具可以发送http请求,这里推荐一个非常直观的工具
安装
vscode插件REST Clinet新建文件
xxx.http编写请求文本
POST /api/user/login HTTP/1.1 Host: study.duyiedu.com Content-Type: application/json { "loginId":"admin", "loginPwd":"123123" }发送请求