Linux网络编程基础:从 MAC 到 IP,理解网络数据是怎么传输的

学习网络编程时,有两个地址经常出现:MAC 地址和 IP 地址。

它们看起来都是用来标识设备的,但作用并不一样。只记住各自的定义还不够,更重要的是弄明白:两台计算机在同一个局域网里怎样通信?如果目标计算机不在本地网络,又该怎么办?

这篇就从局域网通信开始,把数据传输过程中涉及的几个概念串起来。

一、同一个局域网中的计算机如何通信?

先考虑一个简单的情况:两台计算机连接在同一个局域网中,它们能不能直接通信?

可以,但前提是它们能够按照相应的网络规则找到彼此,并且具备正常通信的网络连接。

局域网中的主机需要有能够识别网络接口的地址。以以太网为例,这里就涉及 MAC 地址。

1. 认识 MAC 地址

MAC 地址主要用于数据链路层,帮助识别局部链路中的网络接口。

常见的 MAC 地址长度为 48 位,也就是 6 个字节,通常采用十六进制表示,例如:

text 复制代码
08:00:27:03:fb:19

常见的以太网 MAC 地址通常由网络设备厂商分配。不过,实际使用中也可能出现虚拟网卡、软件修改地址等情况,所以不能简单地认为任何设备上的 MAC 地址都绝对唯一且永远不会改变。

在 Windows 系统中,可以通过下面的命令查看网络适配器信息:

bash 复制代码
ipconfig /all

查看网卡信息时,通常可以找到对应的物理地址。

2. MAC 地址有什么用?

在以太网通信过程中,数据帧中会包含源 MAC 地址和目的 MAC 地址等信息。

主机收到一个数据帧后,会根据相应的链路层规则判断它是否应该由当前网络接口接收,再决定如何处理数据。

可以把 MAC 地址理解成局部链路通信中的重要标识。

不过,MAC 地址并不是用来规划跨越整个互联网的传输路径的。要让数据到达其他网络中的主机,还需要 IP 地址和路由机制。

二、为什么还需要 IP 地址?

假设两台主机都在同一个局域网内,通信通常只需要考虑本地链路上的传输。

但如果两台主机相隔很远,数据可能需要经过一个或多个路由器才能到达目标。

如果仅依靠局部链路中的 MAC 地址,就很难建立起跨越多个网络的整体寻址和转发机制。

这时就需要 IP 地址。

1. 认识 IPv4 地址

IP 地址用于网络层的寻址。它帮助网络设备识别 IP 数据包的源地址和目的地址,并结合路由规则决定如何转发。

IPv4 地址是一个 32 位的地址,也就是 4 个字节。平时最常见的形式是点分十进制,例如:

text 复制代码
192.168.0.1

四个数字分别表示地址中的一个字节,每个数字范围为 0~255。

需要注意,IP 地址与主机的关系还涉及网络接口、地址配置、子网等因素。这里先把它理解为网络层进行寻址的重要信息。

2. IP 地址与 MAC 地址有什么区别?

可以先从作用上区分:

对比 IP 地址 MAC 地址
所属层次 网络层 数据链路层
主要作用 网络层寻址与路由转发 链路层节点识别与帧传输
关注范围 可以跨越多个网络 主要用于当前链路上的帧传输
典型长度 IPv4 为 32 位 常见以太网 MAC 地址为 48 位

IP 地址和 MAC 地址并不是互相替代的关系,它们在网络通信中负责不同的工作。

三、跨网络通信时,MAC 地址会变化吗?

假设主机 A 要向另一个网络中的主机 B 发送数据,中间经过路由器 R。

整体过程可以这样理解:

  1. 主机 A 先判断目标 IP 地址是否在本地网络中。
  2. 如果目标位于其他网络,主机 A 通常会把数据交给配置好的下一跳路由器。
  3. 数据在本地链路上发送时,需要构造相应的数据帧,帧的目的 MAC 地址一般是下一跳设备的 MAC 地址。
  4. 路由器收到数据后,处理网络层信息,根据路由表决定下一步转发方向。
  5. 路由器通过新的链路发送数据时,会重新构造链路层帧。
  6. 数据经过一个或多个路由器后,最终到达目标网络,再交付给目标主机。

这个过程里有一个值得注意的地方:

在常见的路由转发过程中,IP 数据包中的源 IP 和目的 IP 通常保持不变,而每一段链路上的源 MAC 地址和目的 MAC 地址可能不同。

这里说的是不考虑 NAT 等会改写 IP 地址的情况。网络层地址与链路层地址之所以同时存在,就是因为它们解决的是不同层次的问题。

可以简单记为:

  • IP 地址帮助确定数据要到哪个网络中的目标主机。
  • MAC 地址帮助数据在当前链路上送到正确的下一跳。

四、网络传输中的数据为什么要分层封装?

前面了解了不同层的作用,现在再看数据是怎样从发送方传到接收方的。

假设应用程序需要发送一段消息。这段消息不能不加处理就直接放到网线上发送,而是要经过协议栈中的多个层次。

发送时,数据通常从上层向下层传递,每经过一层,该层就可以按照协议要求添加自己的控制信息。

这个过程叫作封装(Encapsulation)。

例如,可以把数据大致理解为下面的形式:

text 复制代码
应用层数据
    ↓
传输层首部 + 应用层数据
    ↓
网络层首部 + 传输层数据
    ↓
数据链路层首部 + 网络层数据
    ↓
通过物理介质发送

每一层都会根据自己的协议增加相应的信息。

1. 报头和有效载荷

在学习协议时,经常会看到两个词:报头和有效载荷。

  • 报头(Header): 保存协议处理需要的信息,例如地址、长度、控制字段等。
  • 有效载荷(Payload): 当前协议所承载的上层数据。

可以用一个简单的公式来理解:

text 复制代码
报文 = 报头 + 有效载荷

具体到不同协议,数据的叫法也会变化。

通常,传输层的 TCP 数据称为 TCP 段,UDP 数据称为 UDP 数据报;网络层的 IP 数据称为 IP 数据报;以太网数据链路层通常将其称为帧。

这些名字并不是完全相同的概念,它们对应不同层次的协议数据单元。

2. 接收方如何解包?

数据到达目标主机后,处理顺序与发送时相反。

接收方先由底层协议处理收到的数据,再逐层检查对应的协议头部,并根据头部中的相关信息把数据交给上层。

这个过程叫作解封装(Decapsulation)。

可以这样理解:

text 复制代码
接收以太网帧
    ↓
处理链路层信息
    ↓
识别并处理 IP 数据报
    ↓
识别 TCP 或 UDP 数据
    ↓
交给相应的应用程序

每一层只需要按照自己的协议处理相应的信息,然后将剩余的数据交给合适的上层。

这也是协议分层的一个重要好处:每一层不需要完全了解其他层内部的实现,只需要遵守层与层之间的约定。

五、协议头部为什么重要?

发送方增加报头并不是为了凑格式,而是为了帮助接收方正确处理数据。

例如:

  • 链路层的地址信息可以帮助数据帧在本地链路上传输。
  • IP 头部中的地址信息可以用于网络层寻址和路由转发。
  • TCP 或 UDP 头部中的端口信息可以帮助操作系统将数据交付给对应的网络端点。

不同层次的报头承担不同的职责。如果缺少必要的信息,接收方就可能无法正确判断如何处理收到的数据。

理解封装和解封装后,后面学习 TCP、UDP 或其他协议时,就可以先问自己两个问题:

  1. 这个协议的报头中包含哪些重要字段?
  2. 接收方如何根据这些字段处理数据,并把数据交给上层?

沿着这两个问题分析,理解具体协议会更有条理。

六、总结

MAC 地址和 IP 地址看起来都是地址,但分别服务于不同层次的通信:MAC 地址主要参与局部链路上的帧传输,IP 地址负责网络层寻址和跨网络转发。

当数据需要跨越多个网络时,路由器会根据网络层信息进行转发,并在不同链路上使用相应的链路层封装。

与此同时,数据在发送端会逐层封装,在接收端则逐层解封装。每一层通过自己的协议头部完成相应的处理,再将数据交给下一层。

相关推荐
邪修king1 小时前
Re:Linux系统篇(三十八):进程间通信ChapterSystem V 信号量深度解析|同步互斥、内核源码、C 指针多态、实战代码
java·linux·c语言
霅昪忞昉1 小时前
DSP_28002x的SPI代码注释_文3
笔记·dsp开发
磁场转动100万匹1 小时前
Doris 学习(二):底层架构与三种数据模型深入解析
学习·架构
明天也要努力学习1 小时前
深入理解数据链路层:以太网、MAC 地址与交换机
网络·网络协议
海绵宝宝转agent1 小时前
Leetcode100+面经
java·笔记·学习·算法·leetcode·深度优先
前进的李工1 小时前
Agent 学习笔记 01:从工具调用到 ReAct 循环
笔记·学习·llm·agent·react·工具调用
海绵宝宝转agent1 小时前
LeetCode100个人题解+java面经总结
java·开发语言·笔记·学习·算法
Eloudy1 小时前
`ibv_get_device_list` 实现分析
网络·gpu·rdma
山东孙燕姿1 小时前
前端框架升级:不敢动的组件怎么办
大数据·运维·服务器·网络·人工智能·前端框架