
🔥草莓熊Lotso: 个人主页
❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受!
🎬 博主简介:

文章目录
- 前言
- [一. 数据链路层基础与以太网](#一. 数据链路层基础与以太网)
-
- [1.1 数据链路层的核心作用](#1.1 数据链路层的核心作用)
- [1.2 认识以太网](#1.2 认识以太网)
- [1.3 以太网帧格式详解(RFC 894)](#1.3 以太网帧格式详解(RFC 894))
- [1.4 局域网通信的基本原理](#1.4 局域网通信的基本原理)
- [1.5 数据碰撞与 CSMA/CD](#1.5 数据碰撞与 CSMA/CD)
- [1.6 混杂模式与抓包原理](#1.6 混杂模式与抓包原理)
- [1.7 MTU 对上层协议的影响](#1.7 MTU 对上层协议的影响)
- [二. ARP 协议:IP 地址到 MAC 地址的映射](#二. ARP 协议:IP 地址到 MAC 地址的映射)
-
- [2.1 ARP 协议的作用](#2.1 ARP 协议的作用)
- [2.2 ARP 的工作原理](#2.2 ARP 的工作原理)
- [2.3 ARP 报文格式详解](#2.3 ARP 报文格式详解)
- [2.4 ARP 缓存机制](#2.4 ARP 缓存机制)
- [2.5 ARP 在跨网通信中的作用](#2.5 ARP 在跨网通信中的作用)
- [2.6 实战:获取局域网内所有主机的 MAC 地址](#2.6 实战:获取局域网内所有主机的 MAC 地址)
- [2.7 RARP 协议(了解)](#2.7 RARP 协议(了解))
- [2.8 ARP 欺骗原理与安全问题](#2.8 ARP 欺骗原理与安全问题)
- [三. Linux 内核 ARP 源码解读](#三. Linux 内核 ARP 源码解读)
-
- [3.1 ARP 报文接收函数:arp_rcv ()](#3.1 ARP 报文接收函数:arp_rcv ())
- [3.2 ARP 报文处理函数:arp_process ()](#3.2 ARP 报文处理函数:arp_process ())
- 结尾:
前言
当你在浏览器输入网址按下回车,数据首先会被封装成 IP 数据报,但 IP 数据报并不能直接在物理网络上传输。它必须被进一步封装成以太网帧 ,通过 MAC 地址在局域网内找到下一跳设备。为什么我们的电脑能准确把数据发给路由器,而不是隔壁室友的电脑?为什么 IP 地址已经能标识全球主机,还需要 MAC 地址?这些问题的答案都藏在 TCP/IP 协议栈的数据链路层 中。数据链路层负责解决 "怎么把数据从一个节点传到同一链路的另一个节点"的问题,是网络通信的" 最后一公里 "。本文将从以太网帧格式讲起,深入解析局域网通信原理、MTU 对上层协议的影响,最后拆解 ARP 协议的工作机制与安全问题,带你彻底搞懂数据链路层的核心逻辑。

一. 数据链路层基础与以太网
1.1 数据链路层的核心作用
对比理解网络层 和数据链路层:
- 网络层(IP) :描述数据传输的全程起点和终点,解决 "去哪里" 的问题
- 数据链路层(MAC) :描述数据传输的每一个区间的起点和终点,解决 "怎么去下一跳" 的问题
经典类比(唐僧例子之白龙马):唐僧要去西天取经,IP 地址是 "长安→西天" 的全程路线,而 MAC 地址是每一段路的具体交通工具。白龙马负责把唐僧从长安送到两界山(第一跳),再由孙悟空负责从两界山送到高老庄(第二跳),每一段都只关心当前区间的起点和终点。
1.2 认识以太网
"以太网" 不是一种具体的网络,而是一套技术标准,同时定义了数据链路层和物理层的规范:
- 物理层:规定使用双绞线作为传输介质,支持 10M/100M/1000M 等传输速率
- 数据链路层:定义了以太网帧格式、访问控制方式(CSMA/CD)等
以太网是目前应用最广泛的局域网技术,与之并列的还有令牌环网、无线 LAN 等,但以太网凭借简单、高效的特点占据了绝对主导地位。
1.3 以太网帧格式详解(RFC 894)
以太网帧是数据链路层的基本传输单元,标准格式如下:
| 字段 | 长度(字节) | 作用 |
|---|---|---|
| 目的 MAC 地址 | 6 | 接收方网卡的物理地址 |
| 源 MAC 地址 | 6 | 发送方网卡的物理地址 |
| 类型 | 2 | 标识上层协议类型:0x0800=IP,0x0806=ARP,0x8035=RARP |
| 数据 | 46~1500 | 上层协议数据(IP 数据报、ARP 报文等) |
| CRC 校验 | 4 | 循环冗余校验,检测传输错误 |
关键细节:
- MAC 地址 :48 位(6 字节)全球唯一的物理地址,网卡出厂时固化,格式为
08:00:27:03:fb:19。虚拟机的 MAC 地址可能冲突,部分网卡支持手动修改。 - 数据长度限制 :
- 最大 1500 字节:即MTU(最大传输单元),超过则需要在网络层分片
- 最小 46 字节:不足时自动填充无用数据(PAD),接收方通过 IP 首部的总长度字段区分有效数据和填充

1.4 局域网通信的基本原理
局域网内的所有主机共享同一传输介质,通信采用广播 + 单播的方式:
- 主机 A 要给主机 E 发送数据,封装以太网帧,目的 MAC 填主机 E 的 MAC 地址
- 将帧发送到局域网中,所有主机都会收到这个帧
- 每台主机提取帧的目的 MAC 地址,与自己的 MAC 地址对比:
- 不匹配:直接在链路层丢弃,上层协议完全不知道
- 匹配:接收帧,剥离以太网首部,将数据部分交给上层协议处理
形象类比:在教室里老师喊 "张三",所有人都听到了,但只有张三会站起来回应,其他人都会忽略这个喊话。


1.5 数据碰撞与 CSMA/CD
由于局域网是共享介质的,多台主机同时发送数据会产生数据碰撞 ,导致数据损坏。以太网采用 CSMA/CD(载波监听多路访问 / 碰撞检测) 机制解决这个问题:
- 载波监听:发送数据前先监听信道是否空闲
- 碰撞检测:发送数据时同时监听信道,如果检测到碰撞,立即停止发送
- 碰撞避免:等待一个随机时间后重新尝试发送
这就是为什么宿舍人多的时候网速会变慢:碰撞概率增加,单位时间内成功传输的数据量减少。

1.6 混杂模式与抓包原理
默认情况下,网卡只会接收目的 MAC 是自己的帧。但可以将网卡设置为混杂模式,此时网卡会接收所有经过的帧。
抓包软件(如 Wireshark)就是利用这个原理工作的。这也意味着:同一局域网内的任何主机都可以抓到你的数据,这也是为什么应用层加密(HTTPS)如此重要。
1.7 MTU 对上层协议的影响
MTU(最大传输单元)是数据链路层对上层数据的最大长度限制,以太网标准 MTU=1500 字节。
对 IP 协议的影响
- 如果 IP 数据报长度超过 MTU,会在网络层分片
- 每个分片都有相同的 16 位标识,不同的片偏移和 MF 标志
- 任意一个分片丢失,整个 IP 数据报都会被丢弃,IP 层不负责重传


对 UDP 协议的影响
- UDP 首部 8 字节,IP 首部 20 字节,因此 UDP 数据最大不能超过
1500-20-8=1472字节 - 超过 1472 字节会导致 IP 分片,丢包率大幅上升
- UDP 本身不保证可靠性,因此使用 UDP 时应尽量控制报文大小
对 TCP 协议的影响
TCP 通过 MSS(最大段大小) 机制避免 IP 分片:
- MSS = MTU - IP 首部长度 - TCP 首部长度
- 标准以太网中 MSS=1460 字节(1500-20-20)
- TCP 在三次握手时,双方会在 SYN 包的选项字段(kind=2)中交换自己支持的 MSS 值
- 最终选择较小的 MSS 作为通信的最大段大小
这就是为什么 TCP 的滑动窗口是一段段发送的:每一段的大小都不超过 MSS,确保 IP 层不需要分片。


补充:逻辑闭环




二. ARP 协议:IP 地址到 MAC 地址的映射
2.1 ARP 协议的作用
我们知道 IP 地址可以标识全球主机,但数据链路层只能识别 MAC 地址。ARP(地址解析协议) 的作用就是:根据 IP 地址获取对应的 MAC 地址。
ARP 是一个介于数据链路层和网络层之间的协议,它的报文需要封装在以太网帧中传输。


2.2 ARP 的工作原理
ARP 采用先广播请求,再单播应答的工作方式:
- 主机 A 要和主机 B 通信,知道主机 B 的 IP 地址但不知道 MAC 地址
- 主机 A 在局域网内广播 ARP 请求包:"谁是 IP 地址 <192.168.1.2>?请告诉我你的 MAC 地址"
- 局域网内所有主机都会收到这个请求
- 只有主机 B 发现请求中的 IP 地址是自己的,于是单播 ARP 应答包给主机 A:"我是 <192.168.1.2>,我的 MAC 地址是 08:00:27:03:fb:19"
- 主机 A 收到应答后,就可以用主机 B 的 MAC 地址封装以太网帧进行通信了
形象类比:在教室里你不知道张三的学号,于是大喊一声 "张三是谁?告诉我你的学号",只有张三会回应你,告诉你他的学号。
2.3 ARP 报文格式详解
ARP 报文长度为 28 字节,封装在以太网帧的数据部分:
| 字段 | 长度(字节) | 作用 |
|---|---|---|
| 硬件类型 | 2 | 链路层网络类型,1 = 以太网 |
| 协议类型 | 2 | 要映射的协议类型,0x0800=IP |
| 硬件地址长度 | 1 | MAC 地址长度,6 字节 |
| 协议地址长度 | 1 | IP 地址长度,4 字节 |
| 操作码(op) | 2 | 1=ARP 请求,2=ARP 应答 |
| 发送端以太网地址 | 6 | 发送方 MAC 地址 |
| 发送端 IP 地址 | 4 | 发送方 IP 地址 |
| 目的以太网地址 | 6 | 接收方 MAC 地址(请求时填全 0) |
| 目的 IP 地址 | 4 | 接收方 IP 地址 |

为什么 MAC 地址会出现两次?
细心的读者会发现,源 MAC 和目的 MAC 在以太网首部 和ARP 数据部分各出现了一次,这不是多余的吗?
这是严格的分层设计原则决定的:
- 以太网首部的 MAC 地址是给网卡和交换机看的,决定帧在物理上要发给谁
- ARP 数据部分的 MAC 地址是给操作系统的 ARP 协议看的,用于更新 ARP 缓存表
类比:你寄快递时,快递单(以太网首部)上写了收件人地址,包裹里的退款单(ARP 数据)上也写了收件人地址。快递员只看快递单,商家只看退款单,各司其职。


2.4 ARP 缓存机制
如果每次发送数据都要发 ARP 请求,效率会很低。因此每台主机都维护一个ARP 缓存表,记录 IP 地址到 MAC 地址的映射关系。
- 查看 ARP 缓存表:
arp -a(Windows/Linux 通用) - 缓存条目有过期时间:不同系统默认 15-45 秒,过期后会重新发送 ARP 请求
- 为什么不能永久缓存?因为 IP 地址是动态分配的,主机可能更换网卡或下线

2.5 ARP 在跨网通信中的作用
ARP 不只是在目标子网才会发生,每一跳转发都需要 ARP:
- 主机 A 要访问外网的百度服务器,首先查路由表,发现下一跳是网关 <192.168.1.1>
- 主机 A 发送 ARP 请求,获取网关的 MAC 地址
- 网关收到 IP 数据报后,查路由表发现下一跳是运营商路由器
- 网关发送 ARP 请求,获取运营商路由器的 MAC 地址
- 这个过程会一直重复,直到数据到达目标主机
结论:IP 地址是全程不变的,而 MAC 地址每经过一跳都会被重写。
2.6 实战:获取局域网内所有主机的 MAC 地址
我们可以通过ping 扫描 + ARP 缓存的方式获取局域网内所有在线主机的 MAC 地址:
bash
# 1. 扫描局域网内所有IP(以192.168.1.0/24为例)
for i in {1..254}; do ping -c1 -W1 192.168.1.$i > /dev/null 2>&1 & done
# 2. 查看ARP缓存表,获取所有在线主机的MAC地址
arp -a
原理:ping 命令会触发 ARP 请求,对方主机回复后,MAC 地址就会被缓存到本地 ARP 表中。
2.7 RARP 协议(了解)
RARP(逆地址解析协议) 的作用与 ARP 相反:根据 MAC 地址获取 IP 地址。
- 主要应用场景:早期的无盘工作站,启动时没有 IP 地址,通过 RARP 向服务器请求分配 IP
- 现在已被 DHCP 协议取代,几乎不再使用

2.8 ARP 欺骗原理与安全问题
ARP 协议有一个致命的缺陷:它不验证 ARP 应答的合法性 ,只要收到 ARP 应答就会更新自己的缓存表。这就导致了ARP 欺骗攻击的可能。
中间人攻击原理:
- 攻击者主机 M 向主机 A 发送大量 ARP 应答:"我是网关 <192.168.1.1>,我的 MAC 地址是 macM"
- 同时向网关发送大量 ARP 应答:"我是主机 A <192.168.1.2>,我的 MAC 地址是 macM"
- 主机 A 和网关的 ARP 缓存都会被更新,认为对方的 MAC 地址是攻击者的 MAC
- 所有主机 A 和网关之间的流量都会经过攻击者主机 M,攻击者可以窃听、篡改数据
断网攻击原理:
攻击者向目标主机发送 ARP 应答,将网关的 IP 地址映射到一个不存在的 MAC 地址,导致目标主机无法上网。
- 下面的图中这个通过打开百度看透全栈可以关注一下


三. Linux 内核 ARP 源码解读
Linux 内核中 ARP 协议的实现位于net/ipv4/arp.c文件中,核心函数包括arp_rcv()(处理接收的 ARP 报文)和arp_send()(发送 ARP 请求 / 应答)。
3.1 ARP 报文接收函数:arp_rcv ()
c
int arp_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
struct arphdr *arp;
struct net *net = dev_net(dev);
// 检查报文长度是否合法
if (skb->len < sizeof(struct arphdr))
goto out_free;
arp = arp_hdr(skb);
// 只处理以太网和IP地址的ARP请求/应答
if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
arp->ar_pro != htons(ETH_P_IP) ||
arp->ar_hln != ETH_ALEN ||
arp->ar_pln != 4)
goto out_free;
// 根据操作码处理请求或应答
switch (ntohs(arp->ar_op)) {
case ARPOP_REQUEST:
arp_process(net, skb, arp); // 处理ARP请求
break;
case ARPOP_REPLY:
arp_process(net, skb, arp); // 处理ARP应答
break;
default:
goto out_free;
}
return 0;
out_free:
kfree_skb(skb);
return 0;
}
核心逻辑:
- 检查报文长度和协议类型是否合法
- 根据操作码区分 ARP 请求和应答
- 调用
arp_process()函数处理报文,更新 ARP 缓存表
3.2 ARP 报文处理函数:arp_process ()
c
static void arp_process(struct net *net, struct sk_buff *skb, struct arphdr *arp)
{
__be32 sip, tip;
unsigned char *sha, *tha;
struct neighbour *n;
// 提取发送端IP、MAC和目的IP
sip = *(__be32 *)arp->ar_sip;
tip = *(__be32 *)arp->ar_tip;
sha = arp->ar_sha;
tha = arp->ar_tha;
// 更新ARP缓存表:无论请求还是应答,都更新发送端的IP-MAC映射
n = neigh_lookup(&arp_tbl, &sip, dev);
if (n) {
neigh_update(n, sha, NUD_REACHABLE, 0, 0);
neigh_release(n);
}
// 如果是ARP请求,且目的IP是自己,则发送ARP应答
if (arp->ar_op == htons(ARPOP_REQUEST) &&
inet_addr_type(net, tip) == RTN_LOCAL) {
arp_send(ARPOP_REPLY, ETH_P_ARP, tip, dev, sip, sha, tha);
}
}
核心逻辑:
- 提取 ARP 报文中的发送端 IP、MAC 和目的 IP
- 无条件更新ARP 缓存表中发送端的 IP-MAC 映射(这就是 ARP 欺骗的根源)
- 如果是发给自己的 ARP 请求,则发送 ARP 应答
核心考点总结
- 以太网帧格式 :
- 目的 MAC (6B) + 源 MAC (6B) + 类型 (2B) + 数据 (46-1500B) + CRC (4B)
- MTU=1500 字节,最小帧长 64 字节(14+46+4)
- MAC 地址与 IP 地址的区别 :
- IP 地址:全程不变,标识主机的网络位置
- MAC 地址:每一跳都变,标识同一链路内的节点
- MTU 与 MSS :
- MTU:数据链路层最大传输单元,以太网 = 1500 字节
- MSS:TCP 最大段大小,标准值 = 1460 字节
- TCP 在三次握手时协商 MSS,避免 IP 分片
- ARP 协议 :
- 作用:根据 IP 地址获取 MAC 地址
- 工作方式:广播请求,单播应答
- ARP 缓存:有过期时间,不验证应答合法性
- ARP 欺骗:利用 ARP 的无验证特性,实现中间人攻击或断网攻击
结尾:
html
🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!
结语:数据链路层是整个 TCP/IP 协议栈的基础,它为上层网络层提供了可靠的链路传输服务。理解了数据链路层的工作原理,你就掌握了局域网通信的核心逻辑。虽然我们平时上网时几乎感觉不到数据链路层的存在,但它却是网络通信不可或缺的一部分。从以太网帧的封装到 ARP 地址解析,每一个细节都体现了计算机网络设计者的智慧。如果你觉得本文对你有帮助,欢迎点赞、收藏、关注,我会持续分享更多 Linux 底层和网络编程的技术干货。
✨把这些内容吃透超牛的!放松下吧✨ ʕ˘ᴥ˘ʔ づきらど
