admin 管理员组

文章数量: 1184232

🧠 一、基础硬件概念:MAC / PHY / RMII

1. 以太网物理层到底是什么?

在以太网通信中,最底层的就是物理层(Physical Layer)
这一层负责传输最原始的电信号,也就是“0”和“1”。

简单来说:

  • 当你在 MCU 代码里写 ETH_SendFrame() 时,最终这些数据会被转化为电平信号,

  • 然后通过网线(通常是双绞线)传输给对方设备。

这些信号并不是“高1低0”这么简单,而是经过专门的编码方式(比如 MLT-3、NRZ、NRZI 等),确保在不同速率(10M / 100M / 1000M)下能正确传输。

2. MAC 与 PHY 是什么关系?

以太网的硬件部分通常被分为两个核心模块:

模块全称主要职责
MACMedia Access Control(媒体访问控制)处理帧封装、地址识别、冲突检测、发送/接收控制
PHYPhysical Layer Transceiver(物理层收发器)负责把数字信号转成电信号、以及把接收到的电信号转回数字信号

可以这样理解:

  • MAC 关心“怎么组织数据包、何时可以发、地址是谁”;

  • PHY 关心“怎么把这些 0 和 1 发到网线上”。

两者之间通过一个标准化接口连接,这个接口就是 MII / RMII / RGMII 之一。

3. RMII 接口是什么?为什么存在?

RMII(Reduced Media Independent Interface,简化媒体独立接口)
是一种连接 MAC 与 PHY 的标准硬件接口。

它和 SPI、I²C、UART 一样,也是一种“硬件信号标准”。
区别在于:

  • SPI / I²C / UART 用来连接外设(传感器、存储器等),

  • RMII 专门用来连接网络接口芯片(PHY)。

RMII 的设计目标是:
在保证速度(100Mbps)的前提下,减少引脚数量(MII 需要 16 根线,RMII 只要 9 根)。
它定义了诸如 TXD、RXD、REF_CLK、CRS_DV、TX_EN 等信号线。

可以这样理解:

RMII 就是 MAC 和 PHY 之间传输“以太网比特流”的物理通道。
这些信号线上传输的,正是你看到的以太帧中的 0/1 比特。

4. MAC 地址从哪里来?

每个网络设备都有一个全球唯一的 MAC 地址,共 6 个字节(48 位)。
前 3 个字节(高位部分)由 IEEE 分配给芯片厂商,称为 OUI(组织唯一标识符)
后 3 个字节由厂商自行编号。

例如:

00-1A-92-xx-xx-xx  →  属于 Realtek
00-80-E1-xx-xx-xx  →  属于 Microchip

在 STM32 这种嵌入式芯片上:

  • 有的型号带内置 MAC 地址(烧录在寄存器或 OTP 存储区);

  • 如果没有,工程师也可以手动配置一个地址(通常写在 Flash 参数区)。

注意:
MAC 地址在全世界范围唯一
但只在**同一个局域网(LAN)**中起作用。
也就是说,即使两个设备 MAC 地址相同,只要它们不在同一个网段,就不会冲突。

5. MAC、PHY 与协议栈的关系

在 STM32 或其他 MCU 系统中,以太网驱动层通常这样分工:

应用层(例如 lwIP、Modbus TCP、HTTP)
     ↓
TCP/IP 协议栈(lwIP)
     ↓
以太网驱动(ETH DMA、描述符等)
     ↓
MAC 控制器(内部外设)
     ↓
RMII / RGMII 接口
     ↓
PHY 芯片(如 DP83848、LAN8720)
     ↓
网线

可以看到:

  • lwIP 负责协议解析(IP、TCP、UDP 等);

  • MAC 驱动 负责收发帧;

  • PHY 负责物理层信号。

“ETH DMA + 描述符” 是让以太网帧自动搬进搬出的机制,
驱动程序负责配置它们,让 MAC 硬件真正动起来。

DMA 要知道:

  • 数据在哪里(内存地址);

  • 数据长度;

  • 发还是收;

  • 发完了要通知谁。

这些信息都被放在一个结构体中,称为 描述符(Descriptor)

STM32 的以太网驱动通常会建立一组这样的描述符链表,比如:

Tx_Desc[4] // 4个发送描述符 Rx_Desc[4] // 4个接收描述符

每个描述符都包含:

typedef struct { uint32_t Status; // 状态位,比如是否发送完成 uint32_t Control; // 控制信息,比如帧长度 uint32_t Buffer1Addr; // 数据缓冲区地址 uint32_t NextDescAddr; // 下一个描述符地址(形成链表) } ETH_DMADescTypeDef;

DMA 会自动顺着这条链表工作,
比如:

  • 当前帧发完了 → 自动跳到下一个描述符;

  • 如果帧还没准备好 → 暂停等待;

  • 如果收到帧 → 填好描述符,触发中断告诉软件去读。

它们配合起来,形成完整的以太网通信路径。

6. 小结

层级模块职责对应标准
物理层PHY电信号传输与检测IEEE 802.3
数据链路层MAC帧封装、地址识别、冲突检测IEEE 802.3
MAC 与 PHY 接口RMII定义信号线与时序RMII 规范

一句话总结:

PHY 发电信号,MAC 组织帧数据,RMII 连接两者。

🌍 二、OSI 七层模型总览

OSI(Open System Interconnect)七层模型是一种将计算机网络通信协议划分为七个不同层次的标准化框架。每一层都负责不同的功能,从物理连接到应用程序的处理。这种模型有助于不同的系统之间进行通信时,更好地理解和管理网络通信的过程。
OSI定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层),即ISO开放互连系统参考模型。

2.1第一层:物理层(Physical Layer

🧱 1. 物理层是什么?

物理层即电平

物理层(Physical Layer)负责:

  • 用电信号(高低电平)、光信号、或无线波来传输比特(bit)

  • 定义线的数量、电平标准、时序、时钟、速率

在以太网里,物理层通常是PHY芯片在干这件事。
它把 MAC 给它的数字数据,变成实际的模拟波形发到网线上。

⚙️ 2. RMII 在哪一层?

RMII 是 MAC 和 PHY 之间的接口标准
它规定了:

  • 数据线:TXD[1:0] / RXD[1:0]

  • 控制线:TX_EN / CRS_DV

  • 时钟线:REF_CLK (50MHz)

  • 管脚方向和时序。

👉 所以 RMII 上跑的,就是0 和 1 的电平信号
它们属于物理层的“接口部分”

📡 3. PHY 在做什么?

PHY 把 RMII 里的 0/1:

  • 通过编码调制(例如 MLT-3、PAM5)转换成波形;

  • 通过双绞线(RJ45)发出去;

  • 从网线上收到波形后,再解码成 0/1;

  • 再通过 RMII 送回 MAC。

所以:

RMII上传的是逻辑电平信号,网线上传的是模拟电信号。
这两部分合在一起就是“物理层”的全部过程。

2.2 第二层:数据链路层(Data Link Layer)


这一章是整个以太网通信的核心层 ——
在物理层之后,我们真正开始讨论“一个网络数据帧的样子”和“设备如何通过 MAC 地址通信”。

一、什么是数据链路层?

物理层只是传“0 和 1”,
但它根本不知道这些 0/1 属于哪一台设备、哪一条消息。

它解决的是——

在同一个局域网(LAN)内,两台设备怎么准确找到彼此并传输数据。

于是数据链路层就出现了,
它要解决三个问题:

问题举例
1️⃣ 谁发的?发给谁?MAC 地址(地址标识)
2️⃣ 哪一段是完整的消息?帧结构(Frame)
3️⃣ 数据有没有传错?CRC 校验

在 OSI 七层模型中,数据链路层(Data Link Layer)
是连接“物理层”和“网络层”的桥梁。

如果物理层只负责“电信号的传输”,
那数据链路层负责的就是“如何在这些信号中分辨一个个有效的帧”。

换句话说:

数据链路层让一堆电平信号变成“有边界、有意义、有地址”的数据包。

2、以太网帧结构(Ethernet Frame)

MAC 层把上层(IP 层)给的数据,打包成如下结构:

字段长度(字节)说明
前导码 (Preamble)7用于同步时钟(0x55)
帧开始定界符 (SFD)1固定为 0xD5,表示帧开始
目的 MAC 地址6表示要发给谁
源 MAC 地址6表示谁发的
类型 / 长度2表示上层协议类型(如 0x0800 表示 IPv4)
数据 (Payload)46–1500实际内容(如 IP 报文)
FCS(帧校验序列)4CRC32 校验码,用于检测错误

举个例子:

假设有一个以太帧:

目标MAC:FF-FF-FF-FF-FF-FF  
源MAC:00-80-E1-01-02-03  
类型:0x0806(ARP协议)

这说明:

  • 它是一个 广播帧(目标全是 FF);

  • 数据内容是 ARP 请求

  • 意思是:“谁是 192.168.1.1?请告诉我你的 MAC 地址!”

🧠 关键点:

  • 每个以太网帧最小 64 字节,最大 1518 字节。

  • CRC 由 MAC 计算,PHY 负责附带发送。

  • MAC 地址是全局唯一的“身份标识”。

以太网帧中有一个 2 字节的字段,用来标识这帧数据属于哪种协议。

常见值如下:

类型值协议
0x0800IPv4
0x0806ARP
0x86DDIPv6
0x88CCLLDP(链路层发现协议)

例如:

当类型是 0x0800,数据部分的内容就是一个 IP 包

当类型是 0x0806,数据部分是 ARP 报文


3、MAC 地址是哪里来的?

每个带以太网功能的设备(网卡、PHY 模块、MCU 带 MAC 控制器)都有:

  • 一个 唯一的 48 位地址

  • 由 IEEE 分配;

  • 通常写在设备的出厂 EEPROM 或 MAC 寄存器里。

📗 例如:

源 MAC: 00-11-22-33-44-55
目的 MAC: 00-11-22-33-44-66

当帧发送时,MAC 会比较目标地址是否匹配:

  • 如果匹配 → 接收;

  • 不匹配 → 丢弃(除非是广播帧)。


4、帧传输过程简图

应用层数据
   ↓
传输层 (TCP/UDP)
   ↓
网络层 (IP)
   ↓
数据链路层 (MAC) ← 加上MAC地址、类型、CRC
   ↓
物理层 (PHY/RMII) ← 转成0/1电平信号
   ↓
网线传输

5、一个真实的例子(Wireshark 抓包)

Wireshark 中看到的一帧示例:

字段内容
DestinationFF:FF:FF:FF:FF:FF (广播)
Source00:11:22:33:44:55
Type0x0800 (IPv4)
DataIP包内容
FCSCRC 校验值

Wireshark 会根据 Type 字段(0x0800)知道:
“哦,这个帧的上层是 IPv4 协议。”

以太网帧的“目的 MAC 地址”决定了通信方式:

类型目标地址特点
单播(Unicast)精确的某个 MAC一对一通信
广播(Broadcast)FF:FF:FF:FF:FF:FF一对所有通信
多播(Multicast)01:XX:XX:XX:XX:XX一对多通信

示例:

  • 当设备发一个广播帧:所有设备都会收到。

  • 当设备发一个单播帧:只有匹配的 MAC 才会接收。

  • 多播则常用于特定组播通信(比如 IGMP、视频流)。


6、交换机的作用(在数据链路层)

功能说明
封装把上层数据打包成以太网帧
寻址使用 MAC 地址区分设备
差错检测CRC 校验,保证数据可靠性

交换机工作在数据链路层(第二层),它的核心功能是:

根据 MAC 地址,决定每个以太帧应该从哪一个端口发出。

它内部有一张 MAC 地址表(MAC Address Table):

MAC 地址所在端口
00-80-E1-01-02-03Port1
00-80-E1-05-06-07Port2

当一个新的帧到来时:

  1. 交换机先看“源 MAC”,把它和入口端口记录进表;

  2. 再看“目的 MAC”:

    • 如果在表中 → 只转发到对应端口;

    • 如果不在表中 → 广播给所有端口;

    • 如果是 FF:FF:FF:FF:FF:FF → 直接广播。

📘所以:

交换机不像集线器那样“傻广播”,
而是“有记忆、有选择”的转发设备。

7、ARP 的位置

在以太网中,IP 层只认识 IP 地址
但要真正发出帧,还得知道对方的 MAC 地址

于是有了 ARP(Address Resolution Protocol,地址解析协议)

ARP 工作机制:

  1. 设备广播问:“谁的 IP 是 192.168.1.5?”

  2. 对方设备单播回应:“是我,我的 MAC 是 00-80-E1-11-22-33。”

  3. 两边把 IP ↔ MAC 的映射保存到 ARP 表中。

这就是为什么:

即使我们平时只用 IP 通信,底层仍然依赖 MAC。


8、小总结

作用实现者
物理层传输 0/1 信号PHY + RMII
数据链路层组帧、寻址、校验MAC 控制器
名称功能单位
物理层PHY传输比特流(0/1)比特(bit)
数据链路层MAC封装帧、地址识别、差错检测帧(frame)

一句话总结:

物理层解决“信号怎么传”;
数据链路层解决“数据发给谁”。

2.3 第三层:网络层(Network Layer)

这一层解决的核心问题只有一句话:

如何让数据从一个网络跳到另一个网络。

1、概念

(1)局域网LAN:

想象一下:

  • 你家有几台设备:电脑、手机、打印机

  • 都连着同一个路由器的 Wi-Fi

这些设备之间:

  • 能互相通信(例如打印文件、共享文件夹)

  • 即使断网(拔掉路由器的WAN线)也能互联

👉 这种小范围、内部通信的网络,就叫做:

局域网(LAN, Local Area Network)

  • “局域网”这个圈子里,每个设备都能直接找到对方;

  • 彼此用 MAC 地址IP 地址 通信;

  • 不需要经过“外网”。

📦 举个例子:

设备IP 地址
电脑192.168.1.10
打印机192.168.1.20
手机192.168.1.30

这三台设备都连在同一个路由器上,
它们组成了一个小范围的网络:LAN

(2)网段(Network Segment):

LAN 里每个设备有一个 IP 地址。
例如:

192.168.1.10
192.168.1.20
192.168.1.30

前面 192.168.1 部分相同,只有最后一段不同。
这说明它们在同一个网段(Network Segment)

网段 = 一群能直接互通的 IP 地址范围。

(3)子网掩码(Subnet Mask)

子网掩码(Subnet Mask)告诉设备:

  • 哪些 IP 属于我这个网段;

  • 哪些是外网(需要路由)。

例如:

IP: 192.168.1.10
子网掩码: 255.255.255.0

掩码中“255”表示网络号,“0”表示主机号。
也就是说:

  • 网络号 = 192.168.1

  • 主机号 = 10

因此:

  • 192.168.1.20 → 同网段 ✅

  • 192.168.2.20 → 不同网段 ❌

2、它要解决的问题是什么?

在同一个网关(即同一个局域网)下,每个设备的 IP 地址已经唯一标识了它,那为什么还要通过 MAC 地址进行通信?

层级名称职责传输单位
第2层数据链路层在同一局域网内传输数据帧帧(Frame)
第3层网络层在不同网络之间路由和转发数据包(Packet)

简单理解:

数据链路层负责“同一个小区的楼内通信”;
网络层负责“跨小区、跨城市的通信”。

在以太网中,网络层最常用的协议就是 IP 协议(Internet Protocol)

  • 关键点:IP 地址 ≠ 物理通信地址
对比项MAC 地址IP 地址
定义层级数据链路层网络层
作用范围局域网(LAN)跨网段(WAN / Internet)
固定性通常写死在硬件中可配置、可变
长度6 字节(48 位)IPv4:4 字节(32 位)

因为:

  • 交换机工作在数据链路层,只认 MAC,不认 IP。

  • 以太网帧的收发完全依赖 MAC 地址。

  • 如果只有 IP,交换机根本无法决定该从哪个端口发出去。

所以:

  • MAC 是局域网内的真实传输地址

  • IP 是逻辑寻址,用于找到目的设备的“逻辑身份”。

  • IP 是逻辑层面的地址,只存在于软件协议栈的世界。以太网的硬件(网卡、交换机)根本看不懂 IP 地址

MAC 解决“怎么在局域网里找到设备”;
IP 解决“在哪个网段、哪个设备上通信”。

你现在知道:

  • 数据链路层能在**同一个局域网(LAN)**里通信;

  • 它通过 MAC 地址 找设备。

但问题来了👇

如果两台设备不在同一个网段,MAC 地址就找不到对方了。

比如:

你的电脑:192.168.1.10
远程服务器:8.8.8.8

这时,仅靠 MAC 地址是到不了的。
于是——

网络层(IP 层) 就出现了,它负责:
“把数据从一个网络送到另一个网络”。

当数据太大时(例如 TCP 大包),
超过以太网 MTU(一般1500字节)就会被 IP 层拆分成多片。

  • 每片带有相同的标识号;

  • 目标端再根据“偏移量”重组还原。

⚠️ 嵌入式里 lwIP 通常配置不分片(节省内存),
上层应用要控制发送长度。

3、网络层的核心:IP 协议

IP(Internet Protocol)是网络层的核心协议。
它给每台设备分配一个唯一的“逻辑地址” —— IP 地址。

概念示例作用
MAC 地址00:11:22:33:44:55物理网卡身份(局域网内有效)
IP 地址192.168.1.10网络逻辑身份(全网有效)

MAC像身份证,IP像家庭住址。
身份证只在本地派出所有用,住址才能邮寄全国。

4、IP 数据包结构(IPv4)

字段长度 (字节)说明
版本 + 头长度1通常是 0x45(IPv4)
服务类型 (TOS)1QoS 优先级
总长度2整个包长度
标识 + 标志 + 片偏移4用于分片
生存时间 (TTL)1防止无限循环
协议号1表示上层协议(TCP=6,UDP=17)
头部校验和2IP 头错误检测
源 IP 地址4谁发的
目的 IP 地址4发给谁
数据部分可变上层内容(TCP/UDP数据)

🧠 MAC 负责一跳(局域网),
🧠 IP 负责多跳(跨网络)。

IP层不关心应用内容,只负责“送到目标IP”

它不管是 HTTP 还是 Modbus,只管根据目标IP决定下一跳发给谁。

5、子网划分(Subnet)

网络层还定义了“子网”概念,用于分组管理。

一个 IPv4 地址是 32 位(二进制),分为两部分:

IP 地址 = 网络号(Network ID) + 主机号(Host ID)

举个例子:

IP: 192.168.1.10
子网掩码: 255.255.255.0

这代表:

  • 网络号:192.168.1

  • 主机号:10
    即:只有在同一个网络号下的设备才能直接通信。

如果要发给别的网段(例如 192.168.2.x),
就得交给一个“中间人”——路由器(Router)

6、ARP(Address Resolution Protocol,地址解析协议)

 同一个网段通信:

设备IP 地址MAC 地址
电脑A192.168.1.1000:11:22:33:44:55
STM32192.168.1.1200:11:22:33:44:66

现在电脑A要发包给 STM32:

步骤 1️⃣:上层决定目标 IP

  • TCP/IP 协议栈知道目标 IP 是 192.168.1.12。

  • 它判断:目标 IP 在同一个子网(192.168.1.x)。

  • 所以不用经过网关,直接发过去。

步骤 2️⃣:ARP 查 MAC

  • 电脑A发现自己不知道 192.168.1.12 的 MAC;

  • 它广播 ARP:

谁的 IP 是 192.168.1.12?

STM32 回复:

我的 MAC 是 00:11:22:33:44:66
  • 电脑A 记录下来。

步骤 3️⃣:以太网帧封装

电脑A 准备发送的数据包结构如下:

内容
以太网层(硬件)目标MAC = 00:11:22:33:44:66源MAC = 00:11:22:33:44:55
IP层(逻辑)目标IP = 192.168.1.12源IP = 192.168.1.10
上层数据(TCP/UDP)应用数据

步骤 4️⃣:以太网传输

  • 电脑A把帧发到交换机;

  • 交换机查自己的 MAC 地址表:

00:11:22:33:44:66 → 接口3
  • 交换机就只从“接口3”把帧送到 STM32;

  • STM32 收到后,根据 IP 层发现目标IP正是自己 → 处理。

不同网段通信:

假设:

  • A设备:192.168.1.10 / 24

  • 目标:192.168.2.20

  • 默认网关:192.168.1.1(MAC=GW1)

步骤:

1️⃣ A先判断目标IP 192.168.2.20 不在同一网段;
2️⃣ 所以它决定把数据交给 默认网关
3️⃣ A发ARP广播:

谁是192.168.1.1?告诉我你的MAC。

4️⃣ 网关回应:

我是192.168.1.1,我的MAC是GW1。

5️⃣ A缓存结果:

192.168.1.1 -> GW1

6️⃣ A 构造以太网帧:

目的MAC = GW1
源MAC = A1
载荷 = IP包(目标IP=192.168.2.20)

7️⃣ 网关收到后,解析IP包的目标地址;
8️⃣ 发现要去 192.168.2.0 网段,就根据路由表转发出去;
9️⃣ 在下一个网段,再通过 新的ARP 查询 找到目标设备的MAC。

📄 这就是 “IP → MAC 的映射”

7、数据转发过程(IP 路由原理)

路由(Routing) 就是找到“到目标IP的下一步方向”。

当你往外发数据时:

1️⃣ MAC 层检查目标 IP 是否同网段

  • 如果是 → 直接发送(在局域网内广播找 MAC)

  • 如果不是 → 把包发给“默认网关(路由器)”

2️⃣ 路由器再根据自己的路由表
把包转发到目标网段,直到到达目标设备。

这就是所谓的 “跨网通信”

1️⃣ 本机有一张路由表(Routing Table)

例如:

目标网络        子网掩码        网关          接口
192.168.1.0     255.255.255.0   本地直连      eth0
0.0.0.0         0.0.0.0         192.168.1.1   eth0

解释:

  • 第1行:如果目标在192.168.1.x网段 → 直接发送;

  • 第2行:否则 → 发送到默认网关192.168.1.1。

2️⃣ 路由器也有路由表

路由器收到包后:

  • 查看目标IP;

  • 查表决定“下一跳”;

  • 不修改数据,只改“源MAC / 目标MAC”;

  • TTL减1;

  • 发到下一个网段。

3️⃣ 数据在路由链路上的变化

变化内容
MAC 层每经过一跳都会换源/目标MAC
IP 层源IP、目标IP 不变
TCP/UDP数据内容不变

💡 这点非常关键:

IP层负责跨网段通信;MAC层只负责本局域网的“这一跳”。

8、从 MAC 到 IP 的关系(总览)

层级地址谁负责有效范围
数据链路层MAC 地址网卡局域网
网络层IP 地址操作系统 / 协议栈整个网络

🧩 关系图:

应用层 → TCP/UDP → IP层(网络层)
                    ↓
           MAC层(数据链路层)
                    ↓
             PHY层(物理层)

数据包在每一层都被“套壳”:

Ethernet 帧包住 IP 包,
IP 包再包住 TCP/UDP 包。

9、小总结

当一个数据包在线上传输时,层层封装的样子是这样:

以太网帧 (Ethernet Frame)
└─ 以太网头 (Ethernet Header)
    ├─ 目标 MAC 地址
    ├─ 源 MAC 地址
    ├─ 类型(Type)
└─ 数据部分 (Payload)
    ├─ [如果Type = 0x0800 → 这是IP包]
    ├─ [如果Type = 0x0806 → 这是ARP包]

💡注意:
以太网头的 Type 字段 就是用来告诉接收方 “里面装的是什么协议”的。
所以 ARP 和 IP 是并列关系,不是包含关系。

概念职责举例
MAC 地址硬件层地址,只能在局域网用00:11:22:33:44:55
IP 地址网络层地址,用于跨网路由192.168.1.10
子网掩码决定哪些设备属于同一网255.255.255.0
网关不同网段之间的“桥”路由器

ARP 实际上是网络层和链路层之间的桥梁

作用
IP层知道“目标IP”
数据链路层只能根据MAC发帧
ARP负责“IP → MAC”的映射查询

一句话总结:

MAC 让数据能在一跳内通信,IP 让数据能走遍全球。

抓包实战链接:

网络抓包分析

2.4 第四层:传输层(Transport Layer

 从物理层的 0/1 电平一路上升,
每一层都“加壳”或“拆壳”,最终让应用层拿到想要的数据。

┌────────────────────────────┐
│ 应用层数据(例如Modbus命令) │
├───────────────┬────────────┤
│ TCP头(源端口、目的端口、序号...) │ UDP头 │ ← 传输层
├────────────────────────────┤
│ IP头(源IP、目的IP、TTL...)      │ ← 网络层
├────────────────────────────┤
│ MAC头(源MAC、目的MAC、类型)     │ ← 数据链路层
├────────────────────────────┤
│ 电平信号(RMII/网线)          │ ← 物理层
└────────────────────────────┘

一、传输层要解决什么问题?

传输层位于网络层(IP)之上,为进程之间提供端到端的数据传输服务

  • 网络层:负责主机到主机的通信(Host-to-Host)

  • 传输层:负责进程到进程的通信(Process-to-Process)

即:

  • IP 层负责“把包送到正确的设备(哪台电脑)”,

  • 但每台电脑里可能有很多程序在同时上网。

比如你的电脑上同时:

  • 浏览器在访问网页

  • QQ 在聊天

  • STM32 上的调试工具在传数据

🧩 问题是:当 IP 层把包送到电脑时——
电脑怎么知道哪个程序该接收这个包?

这就是传输层的工作:
为每个应用分配“端口号(Port)”,并保证通信可靠。

角色目的

角色目的是否主动发起连接端口号特点
客户端向服务器发起通信请求✅ 主动随机端口(临时)
服务器等待客户端来找它❌ 被动固定端口(提前监听)

🧠 那么:

  • 源端口(Source Port)
    👉 客户端用于这次通信的程序专属门牌号
    (例如:你的浏览器这次被分配了 51324)

  • 目的端口(Destination Port)
    👉 服务器上提供服务的程序监听的门牌号
    (例如:网站程序在 443 上监听 HTTPS 请求)

当你在浏览器输入:

https://www.example

其实浏览器做了这些事:

1️⃣ DNS 解析域名 → 得到服务器 IP
例如:www.example → 93.184.216.34

2️⃣ 根据协议自动选择目标端口号

  • HTTP → 默认端口 80

  • HTTPS → 默认端口 443

3️⃣ 建立 TCP 连接

  • 客户端随机挑一个临时端口(比如 51324)作为源端口号

  • 服务器监听在固定端口(比如 443

👉 TCP 连接是这样标识的:

角色IP端口
客户端192.168.1.1051324
服务器93.184.216.34443

地址类型说明作用
IP 地址定位到“哪台设备”网络层
端口号 (Port)定位到“哪一个程序”传输层

端口号举例

应用协议端口
HTTP(网页)TCP80
HTTPSTCP443
DNSUDP53
Modbus TCPTCP502

所以一个完整的网络终点叫做:
IP + 端口号,比如:
192.168.1.10:502 → 某台设备上的 Modbus TCP 服务。

 二、传输层的两种主要协议

协议全称特点典型应用
TCPTransmission Control Protocol面向连接、可靠传输、字节流HTTP、FTP、SMTP
UDPUser Datagram Protocol无连接、不可靠、面向报文DNS、视频通话、游戏

 三、UDP 协议(简单但高效)

1. 特点
  • 无连接(不需要握手)

  • 尽力而为,不保证可靠性

  • 不保证顺序

  • 开销小、延迟低

2. 首部格式(8字节)
字段含义
源端口号发送方进程标识
目标端口号接收方进程标识
长度UDP首部+数据的长度
校验和用于检验数据完整性
3. 应用场景
  • 实时性高、能容忍丢包的应用
    → 比如视频会议、在线游戏、VoIP。

  • 小数据量、请求-应答型
    → 比如 DNS、DHCP。

 四、TCP 协议(复杂但可靠)

 TCP 通过一整套机制确保数据完整、顺序正确

1️⃣ 序列号(Sequence Number)

每一方都需要给“自己发送的数据”编号(seq);每个字节都分配编号,保证顺序。

2️⃣ 确认号(ACK Number)

同时也要告诉对方“我已经收到你多少了”(ack);告诉对方“我已经收到截至哪一个字节”。

例:

收到了 seq=1000~1499
那么发送 ACK=1500(表示期望下一个字节是 1500)

3️⃣ 重传机制

如果 ACK 没按时到达,就重发。

  • 超时重传(RTO)

  • 快速重传(收到三次相同 ACK)

特点

  • 面向连接(三次握手)

  • 可靠传输(确认 + 重传)

  • 流量控制(防止发太快)

  • 拥塞控制(防止网络拥堵)

  • 全双工通信(双方可同时发送)

  • 面向字节流(无边界)

 五、TCP 的关键机制

(1) 三次握手(建立连接)

客户端                          服务器
  SYN=1, seq=x  -------------->
                 <------------  SYN=1, ACK=1, seq=y, ack=x+1
  ACK=1, ack=y+1 -------------->

🧠 目的

  1. 双方确认彼此能收发数据

  2. 同步初始序列号(Seq)

🧮 三次的含义

1️⃣ 客户端 → 服务器:
“我要连接你,我这边的序列号是 x。”

2️⃣ 服务器 → 客户端:
“我收到了,我这边序列号是 y,同时确认你 x+1。”

3️⃣ 客户端 → 服务器:
“我收到了你的确认,一切就绪。”

(1) 四次挥手(断开连接)

客户端                        服务器
  FIN=1 -------------------->
             <--------------  ACK=1
             <--------------  FIN=1
  ACK=1 -------------------->

💡 为什么四次?

因为 TCP 是全双工的。

  • 一方发完自己的数据后,发 FIN 表示“我不再发了”

  • 另一方仍可能有数据要发,所以要单独再发一个 FIN。

完成流程:

在握手时,双方各自选择一个“随机初始序列号”:

客户端: SYN=1, seq=1000
服务器: SYN=1, seq=5000
握手完成后,双方各自维护自己的 seq 计数。

客户端                                       服务器
---------------------------------------------------------------
SYN=1, seq=1000 ---------------------------->
                        <------------------- SYN=1, ACK=1, seq=5000, ack=1001
ACK=1, seq=1001, ack=5001 ----------------->

(建立连接完毕)

发送数据:
seq=1001, len=100 --------------------------->
                        <------------------- ACK=1101

对方也发数据:
                        <------------------- seq=5001, len=200
ACK=5201 ----------------------------------->

总结:

关键点含义
双方都有独立的 seq因为 TCP 是双向通信
seq 表示本方发送数据的编号以字节为单位计数
ack 表示已收到对方数据的下一个期望编号即 “我收到了你到哪”
每次发数据 seq 会增加数据长度发送 100 字节就加 100
每次收到 ACK 表示对方已确认若未收到 ACK,就可能重传

实战抓包分析:

ireshark抓包分析 TCP三次握手/四次挥手详解

六、嵌入式角度下的理解(STM32)

在 STM32 + LWIP 或 FreeRTOS + TCP/IP 协议栈中:

层级谁负责说明
PHY 层外部 PHY 芯片 (如 LAN8720)发送电平
MAC 层STM32 的以太网控制器收发帧、加校验
IP 层LWIP 协议栈处理 IP 路由
TCP/UDP 层LWIP 协议栈处理端口、握手、重传
应用层你的代码比如 Modbus TCP、HTTP Server

在 STM32(尤其是带 MAC 控制器的 H5、F7、H7 系列)里:

  • MAC 控制器:硬件实现第2层(数据链路层)

  • LWIP 协议栈:软件实现第3~4层(IP、TCP/UDP)

  • PHY 芯片:实现第1层(物理层)

流程是这样的:

1️⃣ 应用层调用 send()
2️⃣ LWIP 把数据打包成 TCP/IP 数据包 →
3️⃣ LWIP 通过驱动(ethernetif.c)把数据交给 MAC →
4️⃣ MAC 通过 RMII 接口把信号发给 PHY →
5️⃣ PHY 把电平信号发到网线 → 完成网络传输。

物理世界                  逻辑/软件世界
───────────────           ────────────────────────
RJ45 网口 ──► PHY 芯片 ──► STM32 ETH MAC ──► TCP/IP 协议栈
                                                │
                                                ├─ TCP 端口 80(HTTP 服务)
                                                ├─ UDP 端口 502(Modbus)
                                                └─ TCP 端口 23(Telnet)

七、“端口与套接字(socket)之间的关系?

Socket = 网络通信的“端点”

一句话概括:

“套接字就是程序在网络通信中的一个身份(或者说门口)。”

也就是说:

Socket = IP地址 + 端口号 + 协议类型 (TCP/UDP)
它唯一标识了通信双方的一端。

比如:

  • 服务器的 Socket:(192.168.1.100, 80, TCP)

  • 客户端的 Socket:(192.168.1.5, 52341, TCP)

这两者组合起来:

Socket Pair = (192.168.1.5:52341, 192.168.1.100:80)

这就是一次 TCP 连接的唯一标识
即使同一台电脑开了很多浏览器标签页,它们的源端口不同,所以每个连接都是唯一的。

[ 应用层 ] ←─── 通过 socket ───→ [ 传输层 (TCP/UDP) ]

八、“当程序通过 socket 发送一段数据时,它是如何一步步变成以太网帧发出去的”

🧭 场景设定:从应用层到物理层的完整旅程

假设你写了一个 TCP 客户端程序(可以是 PC、也可以是 STM32),
执行了这行代码:

send(sock, "Hello", 5, 0);

这短短一行,其实触发了底层 五层网络模型 的全流程👇


🧩 一、应用层(Application Layer)

这是你的程序逻辑所在层。
你调用的 send() 并不直接“发网线信号”,它只是:

把数据(比如 "Hello")交给操作系统的 socket 接口。

此时数据还只是一段内存中的字节序列
例如:

Hello → 48 65 6C 6C 6F (ASCII)

然后操作系统把这段数据交给传输层。


🚚 二、传输层(Transport Layer)——TCP 协议

此时操作系统的 TCP 模块接手。

它会:

  1. 查找你这个 socket 对应的连接(里面包含本地IP、端口、对方IP、端口)。

  2. 把数据切成一个或多个 TCP 段(Segment)

  3. 给每个段加上 TCP 头部。

TCP 头部包含:

  • 源端口号(你的应用程序端口)

  • 目标端口号(服务器端口)

  • 序列号(seq)

  • 确认号(ack)

  • 校验和等

于是得到:

[ TCP头 | Hello ]

📦 TCP 段提供“可靠传输”:保证顺序、重传、确认、无丢失。

TCP 再把这个段交给下层的 网络层(IP 层)


🌍 三、网络层(Network Layer)——IP 协议

网络层接到 TCP 段后,做一件事:

把它“包装”进一个 IP 包(IP Packet)

在 IP 头里,会加上:

  • 源 IP 地址(你设备的 IP,比如 192.168.1.10)

  • 目标 IP 地址(服务器的 IP,比如 192.168.1.100)

  • 协议号(标识上层是 TCP)

于是你现在的数据变成:

[ IP头 | TCP头 | Hello ]

🧠 IP 层负责“找到对方设备”,相当于写上了“收件人和寄件人地址”。

接着 IP 层把包交给 链路层


🧲 四、数据链路层(Data Link Layer)——以太网帧(Ethernet)

网络层知道要发往哪一个 IP 地址,
但局域网通信需要用 MAC 地址,因此链路层要做两件事:

  1. ARP 查询: 查到对方 IP 对应的 MAC 地址(例如 00:1A:2B:3C:4D:5E)

  2. 封装以太网帧:

以太网帧结构:

[ 目的MAC | 源MAC | 类型(0x0800=IPv4) | IP包 | FCS校验 ]

现在数据变成:

[ 以太网头 | IP头 | TCP头 | Hello | FCS ]

🧩 链路层负责“在同一个局域网中找到对方网卡”。


⚡ 五、物理层(Physical Layer)

终于,数据准备发出去了。

链路层会把帧交给网卡(比如 STM32 的 ETH MAC + PHY):

  • MAC 模块把帧转换成比特流;

  • PHY 模块把比特流变成电信号;

  • RJ45 接口把信号送入网线。

电信号在网线中传输,进入交换机 → 路由器 → 最终到达服务器。


🛰️ 六、服务器端的逆向流程

服务器收到电信号后,整个过程反向进行:

物理层 → 链路层 → 网络层 → 传输层 → 应用层

即:

RJ45 → PHY → MAC → IP → TCP → Socket → recv()

最终,服务器程序执行:

recv(sock, buffer, 1024, 0);

得到你发来的 "Hello"


🧭 七、总结流程图(逻辑)
┌──────────────┐
│ 应用层:send()│
└──────┬───────┘
        ▼
┌──────────────┐
│ 传输层:TCP封装│ ← 端口号、序列号、校验
└──────┬───────┘
        ▼
┌──────────────┐
│ 网络层:IP封装 │ ← 源IP、目标IP
└──────┬───────┘
        ▼
┌──────────────┐
│ 链路层:以太网帧 │ ← 源MAC、目标MAC
└──────┬───────┘
        ▼
┌──────────────┐
│ 物理层:电信号传输 │
└──────────────┘

✅ 八、一句话总结

当你调用 send() 时,数据会经过:
应用层 → 传输层(TCP) → 网络层(IP) → 链路层(以太网) → 物理层(电信号)
一层层封装成帧,最终变成电信号通过网线发出。

这就是所谓的:

“数据封装(Encapsulation)”与“分层传输”

2.5 第五层:会话层(Session Layer

会话层的定义:

负责建立、管理和终止通信会话(Session)。

举个例子:

  • 在 OSI 理论里,会话层负责:

    • 维护会话状态;

    • 同步数据流(比如断点续传);

    • 提供“长连接”概念;

    • 标识不同会话 ID。

  • 在实际 TCP/IP 里:

    • 这些功能被 TCP 自己搞定了

    • TCP 本身就能:

      • 建立连接(三次握手)

      • 保持连接(ACK)

      • 关闭连接(四次挥手)

✅ 所以:

TCP 的“连接”已经天然实现了会话层的功能。
因此独立的“会话层”在现代协议栈里几乎不再出现。

2.6 第六层:表示层(Presentation Layer)

表示层负责:

数据格式的表达与转换,让不同系统之间能理解同一份信息。

包括:

  • 编码格式(ASCII、UTF-8、Unicode)

  • 压缩(gzip)

  • 加密/解密(SSL/TLS)

  • 序列化格式(JSON、XML、Protobuf)

在现代协议里:

  • HTTP + TLS → 把表示层功能内嵌在协议里;

  • MQTT/CoAP/Modbus → 自带定义好的数据结构;

  • JSON、CBOR → 由应用层直接解析。

✅ 所以:

表示层功能现在通常由“应用层协议自己实现”,不再是一个独立层。

2.7 第七层:应用层(Application Layer)

🧱 一、应用层的定位

📍 在网络七层模型中:

┌──────────────────────────────┐
│ 应用层(Application Layer) │ ← 你直接接触、编程使用的部分
├──────────────────────────────┤
│ 表示层(Presentation Layer)│
├──────────────────────────────┤
│ 会话层(Session Layer)     │
├──────────────────────────────┤
│ 传输层(TCP/UDP)           │
├──────────────────────────────┤
│ 网络层(IP)                │
├──────────────────────────────┤
│ 数据链路层(Ethernet)      │
├──────────────────────────────┤
│ 物理层(RMII、电平)        │
└──────────────────────────────┘

✅ 应用层是离用户最近的一层
负责定义“通信的内容和格式”。

🌐 二、应用层的作用

“不同的上层应用,用不同的规则解释和组织传输的数据。”

在 TCP/UDP 已经负责“可靠传输”的前提下,
应用层就只需定义通信语义,即——

“数据代表什么,如何解析,如何应答”。

⚙️ 三、常见应用层协议分类

应用层协议基于传输层功能简述
HTTPTCP浏览器访问网页、REST接口、物联网配置界面
FTPTCP文件传输(上传/下载)
SMTP/POP3TCP邮件收发
DNSUDP域名解析(把域名转成IP)
DHCPUDP自动分配IP地址
Modbus TCPTCP工业设备通信(寄存器读写)
MQTTTCP物联网消息发布/订阅
NTPUDP网络授时(同步时钟)
SNMPUDP网络设备监控与管理
CoAPUDP轻量物联网通信协议(用于低功耗设备)
协议示例格式特点
Modbus TCP[MBAP头][功能码][寄存器][数据]工业协议,结构简单,定长/半定长
HTTP文本:GET / HTTP/1.1Web通信协议,纯文本、可读
MQTTCONNECT、PUBLISH、SUBSCRIBE轻量、面向消息的发布订阅
DNS二进制报文查询类协议,请求和应答匹配
DHCP广播模式自动IP配置,用于网络启动

🧰 四、HTTP 请求的全过程(以嵌入式为例)

假设我们在 STM32 上运行一个小型 Web Server,PC 端使用浏览器访问:

http://192.168.1.100/status

浏览器向服务器发出请求:

GET /status HTTP/1.1
Host: 192.168.1.100

我们来看看这一条简单的 HTTP 请求,在每一层中都经历了什么。

1️⃣ 应用层(HTTP)

  • HTTP 协议定义了请求和响应的格式

  • 这里的 GET /status 代表客户端想要读取服务器的 /status 页面。

  • 此时数据仅仅是文本内容,上层程序只生成字符串,还没有网络封装。

2️⃣ 传输层(TCP)

HTTP 建立在 TCP 协议 上。

  • TCP 模块会先通过“三次握手”建立连接:

SYN → SYN+ACK → ACK

连接建立后,它把上面的 HTTP 数据打包成一段 TCP 报文段(Segment):

[TCP Header | HTTP 数据]
  • TCP 提供:

    • 数据顺序保证;

    • 丢包重传;

    • 流量控制。

TCP 报头中包含源端口(随机生成)和目标端口(HTTP 的 80),用于唯一标识通信通道。

3️⃣ 网络层(IP)

TCP 报文段传给 IP 层后,IP 模块会:

  • 加上 IP 报头(源 IP、目标 IP、TTL、协议号等);

  • 计算校验和;

  • 判断目标 IP 是否在本地网段;

  • 如果不在,则通过默认网关转发。

形成 IP 数据包:

[IP Header | TCP 段]

4️⃣ 数据链路层(MAC / Ethernet)

MAC 层负责真正“打包成以太网帧”:

[目的MAC | 源MAC | 类型(0x0800) | IP 数据包 | FCS]
  • 目的 MAC 地址可能是服务器或路由器;

  • 源 MAC 地址是本机的网卡地址;

  • 类型字段 0x0800 表示这是一个 IP 包;

  • FCS(帧校验序列)用于检测传输错误。

5️⃣ 物理层(PHY / RMII)

MAC 将以太帧通过 RMII 接口送给 PHY:

  • PHY 把数据转换成差分电信号;

  • 驱动 RJ45 口的收发;

  • 以太信号沿网线传输到目标设备。

6️⃣ 服务器端的接收路径

服务器接收到信号后执行反向流程:

PHY → MAC → IP → TCP → HTTP Server

最终,服务器在应用层看到原始内容:

GET /status HTTP/1.1
Host: 192.168.1.100

然后服务器生成响应:

HTTP/1.1 200 OK
Content-Type: text/plain

System Status: OK

再经由相同路径返回给客户端。

✅ HTTP 流程总结

应用层的 HTTP 协议只定义数据格式和语义
它不关心数据如何被传送,TCP/IP 负责保证可靠性与路由,MAC/PHY 负责电信号传输。

整体路径:

浏览器(应用层)
   ↓
TCP(传输层)
   ↓
IP(网络层)
   ↓
以太网帧(链路层)
   ↓
PHY信号(物理层)
   ↓
服务器接收并解析

🧩 五、Modbus TCP 的请求应答流程

Modbus TCP 是工业通信中常用的一种应用层协议,它把传统的串口 Modbus 报文直接封装进 TCP 数据中。

1️⃣ 应用层(Modbus TCP 报文)

一个典型的 Modbus TCP 报文结构:

[ MBAP Header | 功能码 | 数据 ]

MBAP Header(Modbus Application Protocol Header)共 7 字节:

字段长度含义
Transaction ID2请求编号,用于一问一答匹配
Protocol ID2固定为 0,表示 Modbus 协议
Length2后续字节长度
Unit ID1设备地址(从站号)

紧随其后是:

  • 功能码(如 0x03 读取保持寄存器)

  • 数据部分(寄存器地址、数量或写入值)

2️⃣ 传输层(TCP)

Modbus TCP 使用 TCP 端口号 502。
TCP 负责建立连接、确保顺序与重传。

封装后:

[TCP Header | MBAP + Modbus Data]

3️⃣ 网络层(IP)

IP 模块加入 IP 头(源/目标 IP 等),
确保包能送达目标主机或通过网关转发。

[IP Header | TCP 段]

4️⃣ 数据链路层(MAC)

MAC 层根据 ARP 表确定目标 MAC,
打包成以太网帧:

[目的MAC | 源MAC | 类型=0x0800 | IP 数据包 | CRC]

5️⃣ 物理层(PHY)

帧经 RMII 接口转为电信号,
通过网线传输到目标控制器。

6️⃣ 目标设备的响应流程

目标设备收到请求:

PHY → MAC → IP → TCP → Modbus TCP 协议栈

协议栈解析 MBAP 头,匹配 Transaction ID,执行对应功能。
例如读取寄存器后返回:

[MBAP Header | 功能码(0x03) | 字节数 | 数据内容]

再经 TCP / IP / MAC / PHY 返回客户端。

✅ Modbus TCP 流程总结

Modbus TCP 与 HTTP 的封装层级完全一致,
只是应用层的内容不同:

HTTPModbus TCP
应用层GET / POST 文本功能码 + 寄存器数据
传输层TCP(端口80)TCP(端口502)
网络层IPIP
数据链路层MACMAC
物理层PHYPHY

一句话总结:

HTTP 是“面向网页”的语言,Modbus TCP 是“面向寄存器”的语言。
但它们在封装结构上几乎一模一样。

🧩 五、嵌入式通信中的角色划分

协议层STM32 负责lwIP 负责PHY 负责
应用层构造协议数据(HTTP/Modbus)--
传输层-TCP/UDP 建立连接、重传、确认-
网络层-IP 封装与路由转发-
数据链路层MAC 控制器封装帧lwIP 调用驱动接口-
物理层--电信号收发(RMII、网线)

理解要点:

  • 应用层只决定“发什么内容”;

  • TCP/IP 层保证“送达且正确”;

  • MAC/PHY 层保证“信号传得出去、收得回来”。

🔧 六、完整通信路径图

[应用层]       GET /status 或 Modbus 请求
      ↓
[传输层]       TCP 建立连接、打包可靠传输
      ↓
[网络层]       IP 封装、选路、分片
      ↓
[数据链路层]   MAC 头封装、CRC 校验
      ↓
[物理层]       PHY 变为电信号发送到网线

也就是说:
应用层 = 你设计的数据通信协议部分
lwIP 把数据可靠地送达,你定义“数据代表什么”。


🧩 七、总结一句话

职责代表协议嵌入式意义
表示层数据编码/加密/压缩TLS、SSL安全通信(HTTPS)
会话层建立与维持连接RPC、TLS长连接管理
应用层定义通信语义HTTP、MQTT、Modbus TCP设备与用户/服务器交互核心

应用层定义了语言(协议格式)与行为(请求与响应)。

TCP/IP 保证语言能被正确送达;
MAC/PHY 保证语言能被听到。

HTTP、Modbus TCP、MQTT、FTP、SNTP……
这些都是应用层协议,只是“说话内容”不同而已。

本文标签: 以太网