🌈 个人主页: 小小、码农的 CSDN 博客
🔥 系列方向: linux网络
💪 学习宣言: 行动胜于空谈,实践出真知

网络通信看起来好像很简单:

主机 A  -----------------→  主机 B

但真正发送一份数据时,背后其实要解决很多问题:

  • 不同计算机之间怎样保证能够互相理解?
  • 为什么网络协议需要分层?
  • OSI 七层模型和五层模型是什么关系?
  • TCP、UDP、IP 这些协议到底在哪里实现?
  • 一份应用数据是怎样经过协议栈发送出去的?
  • 同一个局域网中的两台主机怎样通信?
  • MAC 地址和 IP 地址分别有什么作用?
  • 如果两台主机不在同一个网络中,数据又怎样经过路由器到达目的主机?

这一篇让我们沿着一份数据真正的传输过程,把这些问题串起来。


1. 网络协议与协议分层

不同计算机之间可能存在很多差异:

  • 硬件结构不同;
  • 操作系统不同;
  • 软件环境不同;
  • 数据组织方式不同。

如果每台计算机都按照自己的方式发送和解释数据,那么即使两台计算机已经通过网络连接起来,也无法真正完成通信。

所以,通信双方必须共同遵守一套规则。

这就是网络协议

可以把协议理解成人与人交流时使用的语言。

假设 A 只会汉语,B 只会英语,那么两个人即使面对面,也很难正常交流。

如果双方都使用能够理解的语言,就可以顺利完成信息交换。

对应到计算机网络中:

语言      → 协议
交流      → 通信
说话内容  → 数据

因此:

网络协议就是通信双方共同遵守的一组规则,它规定了数据应该怎样组织、发送和处理。

但真正的网络通信非常复杂,一份数据从一台主机发送到另一台主机,要面对很多不同的问题:

  • 数据应该怎样组织?
  • 怎样确定数据发给谁?
  • 怎样判断数据应该交给哪个应用程序?
  • 数据应该经过哪些网络?
  • 最终怎样通过网卡和传输介质发送出去?

如果把这些问题全部交给一个巨大的协议解决,整个协议会非常难设计,也非常难维护。

于是就有了一个非常重要的思想:

把复杂的网络通信拆成多个层次,每一层只负责解决一类问题。

这就是协议分层

复杂的网络通信
       ↓
      分层
       ↓
┌──────────────┐
│  应用相关问题 │
├──────────────┤
│  数据传输问题 │
├──────────────┤
│  寻址转发问题 │
├──────────────┤
│  链路传输问题 │
├──────────────┤
│  物理传输问题 │
└──────────────┘

1.1 用打电话理解分层

假设 A 想和 B 打电话。

从两个人的角度来看:

A  <──────── 通话 ────────>  B

好像 A 和 B 是直接通信的。

但实际上,A 的声音要先进入通信设备,再经过底层通信网络,最后才能到达 B。

可以简单拆成:

A                         B
│                         │
│        语言层           │
└─────────────────────────┘
│                         │
│      通信设备层         │
└─────────────────────────┘

A 只需要负责正常说话,并不需要关心:

  • 声音怎样转换;
  • 经过了什么线路;
  • 中间经过哪些设备;
  • 最终怎样到达 B。

这说明:

上层只需要使用下层提供的服务,而不需要知道下层具体是怎样实现的。

分层以后还有一个很重要的好处。

假设底层通信设备换掉了,只要它仍然能够向上提供相同的通信能力,上层就不需要跟着改变。

所以分层能够:

  • 降低不同模块之间的耦合;
  • 让每一层专注解决自己的问题;
  • 方便系统维护和排错;
  • 方便某一层独立升级;
  • 更有利于协议标准化。

这就引出了另一个问题:

如果每个厂商都自己设计一套协议体系,会怎样?

计算机网络发展的早期,不同厂商往往拥有自己的网络体系结构:

厂商 A → 协议体系 A
厂商 B → 协议体系 B
厂商 C → 协议体系 C

即使设备已经在物理上连接起来,只要协议体系不同,仍然可能无法正常通信。

因此,网络不仅需要协议,还需要:

标准化的协议体系。

在这样的背景下,OSI 参考模型出现了。


2. OSI 参考模型与 TCP/IP

OSI,全称:

Open Systems Interconnection,开放系统互连。

OSI 参考模型把网络通信划分成七个层次:

应用层
表示层
会话层
传输层
网络层
数据链路层
物理层

学习 OSI 的重点并不是单纯背下这七个名字,而是理解:

网络通信中的不同问题,可以交给不同层分别解决。

2.1 OSI 七层分别解决什么问题

假设主机 A 上的用户要向主机 B 发送一封内容为:

早上好

的邮件。

发送端的数据会从上向下经过协议栈:

应用层
 ↓
表示层
 ↓
会话层
 ↓
传输层
 ↓
网络层
 ↓
数据链路层
 ↓
物理层

接收端则按照相反方向向上处理。

在这里插入图片描述

应用层

应用层直接面向具体的网络应用。

例如:

  • HTTP;
  • FTP;
  • SMTP;
  • Telnet。

在发送邮件这个例子中,用户编写邮件并要求邮件程序把内容发送出去,就属于应用层要处理的问题。

表示层

不同计算机使用的数据表示形式可能不同。

例如,同一段文字可能采用不同编码。

因此,表示层主要解决:

数据应该以什么形式表示。

例如数据格式转换、编码转换等。

会话层

网络通信并不一定只交换一次数据。

例如:

建立通信
   ↓
发送第 1 份数据
   ↓
发送第 2 份数据
   ↓
发送第 3 份数据
   ↓
结束通信

会话层主要负责组织和管理通信双方之间的会话过程。

传输层

传输层主要负责:

为通信双方的应用提供端到端的数据传输服务。

后面会重点学习两个非常重要的传输层协议:

TCP
UDP

网络层

=

网络层需要解决:

数据怎样到达目标主机所在的网络。

这一层会涉及:

  • 网络层地址;
  • 数据应该发往哪里;
  • 跨越多个网络时怎样转发。

IP 就属于网络层协议。

数据链路层

当数据真正进入某一段网络以后,还需要解决:

数据在当前链路中怎样传递。

后面会接触:

  • 以太网;
  • MAC 地址;
  • 数据帧;
  • 交换机。

物理层

最终,所有数据都必须变成能够在真实介质中传播的信号:

二进制数据
   ↓
电信号 / 光信号 / 无线信号
   ↓
真实传输介质

这就是物理层主要解决的问题。

2.2 从 OSI 到 TCP/IP

OSI 帮助我们建立了完整的分层思想。

但真正进入 Internet 和网络编程以后,更经常遇到的是:

TCP/IP 协议体系。

为什么叫做 TCP/IP 五层模型?
这是因为其中的 TCP、IP 协议非常经典、非常重要,具有代表意义,于是就命名成了 TCP/IP 五层模型

需要注意:

TCP/IP 并不是 TCP 和 IP 两个协议简单地放在一起,而是一整套围绕 Internet 通信形成的协议体系。

例如:

应用层:
HTTP、FTP、SMTP……

传输层:
TCP、UDP

网络层:
IP、ICMP……

数据链路层:
以太网等

在后续学习中,通常将 OSI 中的应用层、表示层和会话层统一归入应用层,因此可以按照下面的五层模型理解网络协议栈:

应用层
传输层
网络层
数据链路层
物理层

在这里插入图片描述

后面的网络学习,主要就按照这五层展开。


3. 网络协议栈与操作系统

知道协议怎样分层以后,还需要解决一个非常实际的问题:

TCP、UDP、IP 这些协议到底是谁实现的?

对于普通 Linux 网络程序,可以大致这样理解:

用户空间
┌─────────────────────────┐
│         应用层          │
│   用户程序 / 应用协议   │
└────────────┬────────────┘
             │
           socket
=============│================
             │
内核空间     ↓
┌─────────────────────────┐
│         传输层          │
│       TCP / UDP         │
├─────────────────────────┤
│         网络层          │
│           IP            │
├─────────────────────────┤
│   数据链路相关处理      │
│      网卡驱动等         │
└────────────┬────────────┘
             │
            网卡

也就是说:

应用层主要由用户程序实现,而 TCP、UDP、IP 等传输层和网络层协议的核心功能通常已经由操作系统内核实现。

因此,我们写网络程序时,并不需要自己重新实现 TCP 或 IP。

应用程序通过:

socket

使用操作系统已经实现好的网络协议栈。

所以 Linux 网络编程本质上就是:

学习应用程序怎样通过 socket 使用操作系统提供的网络能力。

Linux 中的 socket 可以通过文件描述符进行操作,因此后面还会继续看到:

read
write
close
……

这些熟悉的接口。

3.1 不同网络设备主要处理到哪一层

把常见网络设备放进五层模型中,也能帮助我们理解它们分别在做什么。

主机

主机需要运行应用程序,同时完成完整的网络通信,因此涉及整个协议栈:

应用层
传输层
网络层
数据链路层
物理层

路由器

路由器最核心的任务是:

根据网络层信息,在不同网络之间转发数据。

因此经典路由器主要涉及:

网络层
数据链路层
物理层

交换机

普通二层交换机主要根据 MAC 地址转发数据帧,因此主要涉及:

数据链路层
物理层

集线器

集线器主要负责物理信号的转发,因此通常放在:

物理层

可以简单记成:

设备 主要处理到哪一层
主机 完整协议栈
路由器 网络层
交换机 数据链路层
集线器 物理层

这里说的是学习网络时常见的经典划分,实际设备可能集成更多功能。


4. 数据封装与分用

现在开始真正观察一份数据。

假设应用程序想发送:

hello

如果只是把 hello 直接扔进网络,其他协议根本不知道:

  • 数据从哪里来?
  • 最终发给谁?
  • 当前应该怎么处理?
  • 处理完成以后应该交给谁?

所以,不同层的协议还需要携带自己的控制信息

这些信息通常按照协议规定的格式组织在协议首部中。

可以类比寄快递。

真正想运输的是:

商品

但快递运输过程中还需要:

寄件人
收件人
地址
联系电话
……

所以真正参与运输的是:

快递信息 + 商品

网络通信也是类似的。

4.1 封装

假设传输层使用 TCP。

应用数据来到传输层以后:

TCP 首部 + hello

再交给网络层。

网络层使用 IP:

IP 首部 + TCP 首部 + hello

继续向下交给数据链路层。

如果当前使用以太网:

以太网相关信息
+
IP 首部
+
TCP 首部
+
hello

整个过程可以抽象成:

应用数据
   ↓
[ TCP | 应用数据 ]
   ↓
[ IP | TCP | 应用数据 ]
   ↓
[ Ethernet | IP | TCP | 应用数据 ]
   ↓
发送到网络

这种:

数据从协议栈上层向下传递,并逐层加入本层协议所需控制信息的过程

就叫做封装

在这里插入图片描述

不同层的数据也经常有不同称呼,例如:

层次 常见名称
传输层
网络层 数据报
数据链路层

4.2 解封装与分用

数据到达目标主机以后,过程正好反过来。

首先收到:

Ethernet
   ↓
IP
   ↓
TCP
   ↓
应用数据

数据链路层先处理自己的信息,然后取出里面的 IP 数据。

网络层再处理 IP,取出里面的 TCP 数据。

传输层继续处理 TCP,最终得到真正的应用数据。

收到数据帧
   ↓
数据链路层处理
   ↓
IP 数据
   ↓
网络层处理
   ↓
TCP 数据
   ↓
传输层处理
   ↓
应用数据

这个过程就是解封装

以后学习任何一个具体协议,都可以重点观察两个问题。

第一个问题:

协议怎样把自己的首部和有效载荷分开?

例如:

IP 首部 + TCP 数据

IP 必须能够判断:

IP 首部在哪里结束?
TCP 数据从哪里开始?

第二个问题:

处理完以后,怎样知道应该把有效载荷交给谁?

例如 IP 的上层可能是:

TCP
UDP
ICMP
……

所以 IP 必须能够告诉接收方:

这份数据接下来应该交给哪个协议处理?

同样,TCP 或 UDP 处理完成以后,也需要确定数据最终应该交给哪个应用程序。

这种把数据交给正确上层协议或应用的过程就是:

分用。
在这里插入图片描述

所以可以简单记成:

发送端:封装

接收端:解封装 + 分用

5. 局域网通信

协议栈内部的数据处理已经清楚了。

接下来看看数据真正离开主机以后,是怎样在局域网中传输的。

假设:

主机 A
   │
交换机
   │
主机 B

A 和 B 位于同一个局域网。

这里主要使用以太网来理解。

5.1 以太网与共享介质

以太网是一种非常重要的局域网技术。

在早期共享介质以太网中,多台设备可能共同使用同一通信介质:

A ─┐
B ─┼──── 共享通信介质
C ─┤
D ─┘

如果多个设备同时发送数据,就可能发生冲突。

因此,早期共享式以太网需要相应的介质访问控制机制,来协调设备对共享链路的使用。

后来随着交换机和全双工以太网广泛使用,每个设备通常拥有相对独立的交换链路,传统共享介质下的碰撞问题已经大幅减少。

不过这里真正需要建立的认识是:

局域网中的设备也需要按照一定的数据链路层规则发送和接收数据。

而以太网中一个非常重要的地址就是:

MAC 地址。

5.2 MAC 地址

MAC:

Media Access Control Address

常见 MAC 地址长度为:

48 bit = 6 字节

例如:

08:00:27:03:fb:19

以太网帧中会携带:

源 MAC 地址
目标 MAC 地址

假设:

主机 A:MAC_A
主机 B:MAC_B

A 要在当前局域网中把数据帧发送给 B,可以简单理解成:

源 MAC:MAC_A
目标 MAC:MAC_B

因此,当前阶段可以先把 MAC 地址理解成:

MAC 地址主要服务于当前链路中的数据帧传递。

可以用教室点名来理解。

假设老师说:

张三,你的作业为什么没交?

教室里的其他人虽然也可能听到这句话,但首先会判断:

老师叫的是不是我?

张三发现叫的是自己以后,才继续处理后面的内容。

目标 MAC 地址也可以帮助设备判断:

这一帧数据是不是发给我的?

【图片占位:多台主机具有不同 MAC 地址的局域网示意图。】

5.3 交换机怎样转发数据帧

现代局域网中,经常使用交换机连接多台设备:

             主机 A
               │
               │
主机 C ───── 交换机 ───── 主机 B
               │
               │
             主机 D

交换机主要工作在数据链路层。

它能够学习并维护:

MAC 地址 ↔ 交换机端口

之间的对应关系。

例如:

MAC_A → 端口 1
MAC_B → 端口 2
MAC_C → 端口 3

如果交换机收到一帧数据:

目标 MAC = MAC_B

那么就可以:

收到数据帧
    ↓
查看目标 MAC
    ↓
查询 MAC 地址表
    ↓
找到 MAC_B 对应的端口
    ↓
向对应端口转发

这里需要区分:

交换机主要解决当前局域网中数据帧往哪个端口转发。

它并不负责决定数据最终应该去哪个网络。

跨网络转发是后面路由器要解决的问题。

5.4 完整走一遍局域网通信

现在假设主机 A 要发送:

hello

给同一局域网中的主机 B。

应用层首先产生:

hello

传输层如果使用 TCP:

TCP 首部 + hello

网络层加入 IP 信息:

源 IP:IP_A
目标 IP:IP_B

到达数据链路层后,因为 B 位于当前局域网,所以这一帧需要交给 B。

假设此时已经知道 B 的 MAC 地址:

源 MAC:MAC_A
目标 MAC:MAC_B

于是整个数据可以简单表示成:

┌────────────────────┐
│ 源 MAC:MAC_A      │
│ 目标 MAC:MAC_B    │
├────────────────────┤
│ 源 IP:IP_A        │
│ 目标 IP:IP_B      │
├────────────────────┤
│ TCP                │
├────────────────────┤
│ hello              │
└────────────────────┘

这里暂时先假设发送方已经知道目标 MAC 地址,具体怎样获得这个地址,后面学习相关协议时再展开。

A 把数据帧发送出去。

交换机看到:

目标 MAC = MAC_B

查询 MAC 地址表以后,把帧转发到 B 所连接的端口。

B 收到以后:

数据链路层
   ↓
处理以太网帧
   ↓
网络层
   ↓
处理 IP
   ↓
传输层
   ↓
处理 TCP
   ↓
应用层

最终应用程序得到:

hello

这就是同一局域网中一次基本的数据通信。


6. 跨网络通信

现在把场景换一下:

主机 A
   │
网络 1
   │
路由器
   │
网络 2
   │
主机 B

A 和 B 不在同一个网络中。

这时,A 就不能只依靠当前局域网中的交换机完成通信。

因为交换机负责的是:

当前局域网内部的数据帧转发。

数据如果要离开当前网络,就需要一个能够连接不同网络的设备:

路由器。

6.1 路由器为什么能连接不同网络

路由器通常拥有多个网络接口。

例如:

网络 1
   │
接口 1
   │
┌────────┐
│ 路由器 │
└────────┘
   │
接口 2
   │
网络 2

接口 1 接入网络 1,接口 2 接入网络 2。

于是路由器就可以位于两个不同网络之间:

主机 A
   ↓
网络 1
   ↓
路由器
   ↓
网络 2
   ↓
主机 B

它的核心任务就是:

根据网络层信息,把数据从一个网络转发到另一个网络。

这时也就能理解:

为什么只有 MAC 地址还不够。

MAC 地址主要关注:

当前这一段链路,数据帧交给谁。

但跨越多个网络以后,我们还需要知道:

这份数据最终要去哪个网络、哪台主机。

因此还需要:

IP 地址。

可以先记成:

IP
 ↓
最终去哪里

MAC
 ↓
这一跳交给谁

6.2 IP 地址和 MAC 地址的区别

IP 地址工作在网络层。

当前主要有:

IPv4
IPv6

IPv4 长度为:

32 bit

通常写成:

192.168.1.10

IPv6 则是:

128 bit

关于 IP 地址组成、子网、NAT 等问题,后面学习 IP 协议时再详细展开。

这里先抓住最重要的一点:

IP 地址用于网络层寻址,并参与跨网络的数据转发。

假设 A 要通过路由器把数据发送给 B:

A
↓
路由器
↓
B

整个通信至少分成两段链路:

第一段:

A → 路由器


第二段:

路由器 → B

可以把它类比成一次长途旅行。

假设最终目的地是上海:

南昌
 ↓
杭州
 ↓
上海

最终目的地始终是:

上海

但是每一段旅程的当前目的地分别是:

南昌 → 杭州
杭州 → 上海

映射到网络中:

IP
 ↓
描述整个网络层通信中的源和最终目标

MAC
 ↓
描述当前这一跳链路中的发送方和接收方

6.3 路由表和下一跳

如果 B 不在 A 当前所在的网络中,那么 A 需要先把数据交给能够继续转发它的路由器。

也就是说:

最终目标:B

当前下一跳:路由器

路由器收到 IP 数据报以后,也需要判断:

下一步应该往哪里走?

因此路由器会根据目标 IP 查询自己的路由信息。

可以简单理解成:

查看目标 IP
     ↓
查询路由表
     ↓
判断应该从哪个接口发送
     ↓
确定下一跳

如果网络更复杂:

A
↓
R1
↓
R2
↓
R3
↓
B

那么对于 A:

最终目标:B
下一跳:R1

对于 R1:

最终目标:B
下一跳:R2

对于 R2:

最终目标:B
下一跳:R3

所以:

最终目的地和下一跳是两个不同的概念。

6.4 完整走一遍跨网络通信

假设:

A 的 IP:IP_A
B 的 IP:IP_B

A 的 MAC:MAC_A

路由器左接口 MAC:MAC_R1
路由器右接口 MAC:MAC_R2

B 的 MAC:MAC_B

网络结构:

A
│
│ 网络 1
│
R
│
│ 网络 2
│
B

A 最终要给 B 发送数据,所以网络层首先构造:

源 IP:IP_A
目标 IP:IP_B

A 判断发现 B 不在当前网络中,因此当前下一跳是路由器。

于是第一段链路是:

A → 路由器

链路层信息可以简单表示为:

源 MAC:MAC_A
目标 MAC:MAC_R1

但是 IP 层仍然是:

源 IP:IP_A
目标 IP:IP_B

所以第一跳:

MAC:
MAC_A → MAC_R1

IP:
IP_A → IP_B

路由器收到数据帧以后,首先处理当前链路层的信息:

收到当前链路的数据帧
        ↓
处理链路层信息
        ↓
取出内部 IP 数据报

然后查看:

目标 IP = IP_B

发现目标并不是自己,于是:

查询路由表
   ↓
决定从哪个接口继续转发
   ↓
确定下一跳

路由器确定下一步以后,就进入了新的链路。

之前使用的:

MAC_A → MAC_R1

只属于第一段链路。

到了下一条链路,需要重新准备链路层信息。

如果下一跳就是 B:

源 MAC:MAC_R2
目标 MAC:MAC_B

但 IP 信息仍然描述:

源 IP:IP_A
目标 IP:IP_B

所以第二跳:

MAC:
MAC_R2 → MAC_B

IP:
IP_A → IP_B

把两段放在一起:

第一跳:

MAC:MAC_A  → MAC_R1
IP :IP_A   → IP_B


第二跳:

MAC:MAC_R2 → MAC_B
IP :IP_A   → IP_B

这里先假设设备已经知道当前下一跳对应的 MAC 地址,具体这个地址怎样得到,后面学习相关协议时再展开。

这张关系图是理解跨网络通信非常关键的一步:

链路发生变化以后,链路层地址也会跟着变化;而 IP 层始终围绕整个网络层通信的源和最终目标进行转发。

6.5 路由器到底做了什么

路由器并不是:

收到一个以太网帧
      ↓
原封不动扔到另一个网络

而是:

收到当前链路的数据帧
          ↓
处理当前链路层信息
          ↓
得到内部 IP 数据报
          ↓
查看目标 IP
          ↓
查询路由信息
          ↓
确定下一跳和出口
          ↓
按照下一条链路重新封装
          ↓
继续发送

所以路由器虽然主要依靠:

IP + 路由表

决定数据往哪里走,但要把数据真正发送到下一跳时,仍然需要使用当前出口的数据链路层。

这也解释了为什么路由器虽然主要工作在网络层,却仍然需要处理 MAC 地址和数据帧。

6.6 IP 为什么能连接不同类型的网络

路由器两边的数据链路技术并不一定完全相同。

例如:

主机 A
   ↓
以太网
   ↓
路由器
   ↓
另一种链路技术
   ↓
主机 B

路由器收到第一种链路的数据以后:

第一种链路帧
      ↓
取出 IP 数据
      ↓
根据目标 IP 转发
      ↓
按照下一条链路重新封装
      ↓
第二种链路帧

也就是说:

链路技术 A
    ↓
    IP
    ↓
链路技术 B

下面的数据链路技术可以变化,但网络层仍然可以使用 IP。

所以:

IP 位于不同底层网络之上,为跨网络通信提供了一套统一的网络层通信方式。

这也是大量不同类型的网络能够互相连接,最终形成 Internet 的重要基础。


7. 总结

回过头来看,这一篇其实一直在回答一个问题:

一份数据到底是怎样从一台主机上的应用程序,到达另一台主机上的应用程序的?

首先,不同计算机想要互相通信,就必须遵守共同的:

网络协议

但网络通信需要解决的问题太多,因此又把这些问题进行:

协议分层

OSI 七层参考模型帮助我们建立了完整的分层思想,而后续学习时通常使用:

应用层
传输层
网络层
数据链路层
物理层

这样的五层模型来理解网络通信。

在 Linux 中,可以大致理解为:

用户程序
   ↓
应用层
   ↓
socket
   ↓
TCP / UDP
   ↓
IP
   ↓
数据链路相关处理
   ↓
网卡

其中应用层主要由用户程序实现,而 TCP、UDP、IP 等协议的核心功能通常已经由操作系统内核实现。

当应用程序需要发送数据时,数据会从上向下经过协议栈:

应用数据
   ↓
TCP 封装
   ↓
IP 封装
   ↓
数据链路层封装
   ↓
发送到网络

接收端则执行相反的过程:

收到数据
   ↓
数据链路层处理
   ↓
IP 处理
   ↓
TCP / UDP 处理
   ↓
分用
   ↓
交给应用程序

如果通信双方位于同一个局域网中:

主机 A
   ↓
交换机
   ↓
主机 B

交换机主要根据 MAC 地址完成当前局域网中的数据帧转发。

如果双方不在同一个网络中:

主机 A
   ↓
网络 1
   ↓
路由器
   ↓
网络 2
   ↓
主机 B

就需要路由器根据目标 IP 地址和路由信息不断选择下一跳,把数据逐步向目标网络转发。

因此,IP 地址和 MAC 地址虽然都会出现在一次网络通信中,但它们解决的是不同层次的问题:

IP 地址
   ↓
网络层
   ↓
解决最终去哪里、跨网络怎样转发


MAC 地址
   ↓
数据链路层
   ↓
解决当前这一跳的数据帧交给谁

跨网络通信时,可以重点记住下面这张关系:

第一跳:

MAC:主机 A → 路由器
IP :主机 A → 主机 B


第二跳:

MAC:路由器 → 主机 B
IP :主机 A → 主机 B

也就是说:

IP 关注的是整个网络层通信的源和最终目标,而 MAC 关注的是当前这一段链路上的发送方和接收方。

路由器收到数据以后,也不是简单地把原来的数据帧直接扔进下一个网络,而是:

收到当前链路的数据帧
        ↓
处理当前链路层信息
        ↓
得到 IP 数据报
        ↓
根据目标 IP 查询路由
        ↓
确定下一跳
        ↓
为下一条链路重新封装
        ↓
继续发送

最终,无论底层经过多少种不同的链路技术,IP 都可以在它们之上提供统一的网络层通信能力。

把整篇文章压缩成一条主线,就是:

协议
 ↓
协议分层
 ↓
OSI / TCP-IP
 ↓
操作系统网络协议栈
 ↓
数据封装与分用
 ↓
局域网中的 MAC + 交换机
 ↓
跨网络中的 IP + 路由器
 ↓
数据最终到达目标应用程序

后面继续学习 TCP、UDP、IP、ARP、路由以及 socket 编程时,基本都可以放回这条主线中理解。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐