1. 认识网络

先有硬件,再有软件。

计算机之间最初是相互独立的。客观上,一个人整理的数据需要交给下一个人;人之间需要协作,计算机之间也是如此。在网络尚未发明之前,计算机彼此孤立,若要将数据传递给另一台计算机,只能通过物理媒介(如软盘、光盘等)进行拷贝。正是因为存在数据共享和协作的需求,才催生了将多台计算机连接在一起的技术,最终形成了计算机网络

在电脑的内部,各种各样的设备都会被集成在主板上,主板本质上就是一套总线结构——只不过主板上的走线被封装在一个机器内部。在主板上,CPU、内存、硬盘等不同的设备通过线路连接,共享同一套通信信道,形成了一种共享介质的通信结构

将这个思想扩展到机器之间: 若是电脑与电脑之间也通过"线"相连,形成一种共享结构,不就可以实现数据的共享了吗?

当计算机1向网线发送数据时,计算机2也有可能同时向网线发送数据。这根网线就相当于计算机1~3共享的公共信道——如果多台计算机同时发送数据,信号就会发生冲突、相互干扰,导致数据损坏。因此这根线的本质就是临界资源,多个计算机就像多个线程,它们对网线的访问相当于对临界资源的访问。

随着连接的计算机增多,冲突发生的概率呈指数级上升,网络性能急剧下降。为了控制冲突并提高效率,局域网不能无限扩大,因此出现了交换机、集线器等设备来解决共享信道的问题——它们通过将大的冲突域分割为多个小的冲突域,或采用交换技术实现点对点通信,从而有效降低冲突概率。

多个局域网之间是相互独立的,但它们也需要进行更大范围的数据共享,因此可以将多个局域网通过路由器等设备连接起来,形成广域网,实现跨地域的互联互通。

在现实世界中,人之间需要互相协作,而计算机是人的工具;人要协同工作,注定了网络的产生是必然的。


2. 协议

学习网络绕不开一个具体的概念,那就是协议。协议是一种"约定"。

计算机A向计算机B发送数据,假设只发送1字节的数据,约定不同的数据表示不同的要求,那么发送不同的数据就可以完成不同的要求。只要将约定做得足够详细,两台机器之间就可以在网络中进行信息传输。这里的约定也就是双方规定好的协议。在磁盘存储中,磁性方向的改变表示1,未改变(或相反方向)表示0,这也是一种约定。

计算机之间的传输媒介是光信号和电信号,通过信号的物理特性(如强弱、频率、相位等)来表示0和1。要传递各种信息,必须约定好双方的数据格式。计算机包含硬件和软件,所以协议在分类上一定会分为硬件协议和软件协议。通信不仅需要协议,还需要在各个层次(包括物理表示方式)上保持一致;否则,即使有协议,也无法正常通信——就像说不同语言的人无法交流。因此,完善的协议需要更细致的规定,并被所有参与者共同遵守。

由于计算机厂商、操作系统和硬件设备多种多样,要实现顺畅通信,就必须采用共同的标准,这就是网络协议的意义。制定协议或标准的通常是业界公认的权威组织,如IEEE、IETF等。自己组装电脑时能混用不同厂商的硬件,是因为它们遵循了统一的硬件接口协议(如PCIe、USB等)。手机和电脑能相互通信,也是因为它们实现了相同的通信协议栈。

协议是一种约定,这种约定会体现在计算机的方方面面,从硬件到软件。协议分为硬件级别的协议和软件级别的协议,接下来讲解的协议都是软件级别的协议。

协议是分层的,在了解协议分层之前先了解软件分层。计算机中大部分的软件组织结构是层状结构,软件的核心设计模式就是层状结构。在计算机领域,有一句经典的说法:"任何问题都可以通过添加一层间接(或软件层)来解决。"

理解了分层的特点,接下来理解软件分层的好处。分层结构在现实世界中处处存在,管理结构就是层状结构的典型例子。计算机是解决现实世界问题的工具,是对现实世界的一种抽象反映。既然现实世界常采用层状结构,那么在计算机世界中,许多问题也可以通过分层结构来解决。

以打电话为例:从逻辑上看,用户A和B直接沟通;但从物理上看,信息经由通信设备传递。因此,可以将通话过程分为两个层次:语言层通信设备层

当通信设备从座机变为手机时,只需更换底层设备,上层的语言交流无需改变;当沟通语言从汉语变为英语时,只需变更语言层,通信设备层保持不变。这说明,只要每一层的功能清晰、接口明确,就可以实现各层独立演化——下层技术的升级不影响上层业务,上层业务的变更不依赖下层实现。

如图所示,不同的用户组合可以通过调整语言层或通信设备层来实现通信,关键在于同层之间协议一致,层与层之间接口标准

总结:软件是分层的,软件分层的核心好处是在软件工程中实现了逻辑解耦,提高了系统的可维护性、可扩展性和灵活性。每一层只需关注自己的职责,通过标准接口与相邻层交互,无需关心其他层的内部实现。


两台主机通过网络通信时,会面临四个核心问题:

  1. 物理传输问题:当主机A向主机B进行数据传输时,一定会经过很多的中间设备,要想将数据从主机A传递到主机B,首先得要将数据从主机A传递到中间设备1,再从中间设备1传递到中间设备2,等等,最后再传递到主机B。那么数据怎么在两个相邻的设备之间进行传递?这涉及信号的编码、调制、传输和接收。
  2. 寻址与路由问题:要将数据从主机A传递到主机B,首先得要知道主机B在哪吧?即主机B的"位置",主机B的"位置"都找不到/不知道,怎么进行数据传输?主机这么多,怎么知道主机B是哪一台?如何解决目标主机的定位和路径的选择问题?例如:生活中的快递,填写好收件地址和收件人的电话,这样才能找到接收方,将快递送达到接收方手中。
  3. 可靠性问题:如果以上两个问题解决了,但是在数据传输的过程中,中间设备损坏了,我们可以知道会出现数据丢失。遇到这种问题,应该怎么办?主机A是否需要重发数据呢?如何保证数据传输的可靠性
  4. 应用语义问题:主机A将数据传递到主机B,这不是目的而是手段,目的是使用传输的数据。主机A将某个数据传递给主机B,这个数据是请求主机B向主机A发送信息,还是向主机B上传音视频文件呢?作为接收方(主机B)应该如何处理主机A传递过来的数据?主机A将数据传递到主机B的目的是处理数据,完成请求或应答的目的。

只有解决这四个问题,网络通信才能真正服务于人的协作需求。

计算机的内部集成设备也是一个小型的网络,只不过硬件之间的距离非常的短。硬件之间也存在协议,只不过计算机内部硬件之间离得非常近,传输介质共享且稳定,数据本来就是通的,所以也就不存在上面的这些问题(尤其是寻址和可靠性问题)。两台主机之间出现以上的问题原因就是物理距离变长了,环境变得复杂,自然会产生新的问题,这些新的问题就是上面提到的四个问题!

为了解决这些问题,因此诞生了网络通信协议,后续用到的协议是TCP/IP协议,协议的本质是一种针对特定问题的解决方案

协议分为四层(从下到上):网卡层(网络接口层/链路层)、互联网层(网络层)、传输层、应用层。这四个问题被协议的四层分别解决,一层解决一个问题:

  • 网卡层解决问题1(物理传输)
  • 互联网层解决问题2(寻址与路由)
  • 传输层解决问题3(可靠性)
  • 应用层解决问题4(应用语义)

问题本身具有层次性,因此协议也采用分层设计,便于开发、维护和演进


3. OSI七层模型

OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范,它把网络从逻辑上分为了7层(从下到上):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

虽然 OSI 模型在理论上非常完整,但在实际工程中,主流互联网采用的是 TCP/IP 协议族。TCP/IP 并未严格对应 OSI 的七层,而是采用了更简洁的结构。在教学和实践中,常使用一种5层模型来讲解 TCP/IP,从下到上为:物理层、数据链路层、网络层、传输层、应用层


各层功能详解

• 物理层

负责光/电信号的传递方式。比如现在以太网通用的网线(双绞线)、早期以太网采用的同轴电缆(现在主要用于有线电视)、光纤,现在的WiFi无线网使用电磁波等都属于物理层的概念。物理层的能力决定了最大传输速率、传输距离、抗干扰性等。集线器(Hub)工作在物理层。集线器功能:将衰减信号进行放大,实现信号的再生和广播转发,支持数据实现网络级别的长距离传输。

• 数据链路层

负责设备之间的数据帧的传送和识别。例如网卡设备的驱动、帧同步(从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作。有以太网、令牌环网、无线LAN等标准。交换机(Switch)工作在数据链路层。交换机的核心工作:通过学习MAC地址建立转发表,实现数据帧的定向转发(而非广播),将大的冲突域分割为多个小的冲突域,从而显著降低碰撞概率,提升局域网效率。

• 网络层

负责地址管理和路由选择。例如在IP协议中,通过IP地址来标识一台主机,并通过路由表的方式规划出两台主机之间的数据传输的线路(路由)。路由器(Router)工作在网络层。IP地址的概念就是网络层中的,主要解决主机定位和路径确定问题。IP地址就像我们在学校中的学号,可以根据学号来找到学校中对应的学生。学号有固定的格式,IP地址也有——这种逻辑地址与物理位置无关,使得主机可以在不同网络间移动而保持标识不变。

• 传输层

负责两台主机之间的端到端数据传输。如传输控制协议(TCP),能够确保数据可靠的从源主机发送到目标主机;用户数据报协议(UDP)则提供无连接的尽力交付服务。传输层通过端口号区分同一主机上的不同应用程序,实现进程到进程的通信。

• 应用层

负责应用程序间沟通,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、超文本传输协议(HTTP)、网络远程访问协议(Telnet)等。网络编程主要就是针对应用层。应用层协议定义了数据的语义和交互规则,使得不同厂商的软件能够互操作。

这种分层方式之所以有效,是因为网络通信中的核心问题本身具有层次性。我们之前提到的四个关键问题,恰好可以由这四层分别解决:

  • 数据链路层 解决问题1:如何在两个相邻设备之间可靠地传递数据帧;
  • 网络层 解决问题2:如何定位目标主机并选择传输路径
  • 传输层 解决问题3:如何保证端到端的数据可靠传输
  • 应用层 解决问题4:如何理解和处理数据的业务含义

4. TCP/IP 协议与操作系统之间的关系

操作系统大部分是使用C语言编写而成,再加上少部分的汇编语言。网络协议栈本身也是用 C 语言实现的,并且通常被集成在操作系统的内核中。

无论是 Windows 系统还是 Linux 系统,所有主流操作系统都具备网络功能,因此每个操作系统都内置了自己的 TCP/IP 协议栈。

尽管不同操作系统的协议栈代码实现不同,但它们都遵循相同的 TCP/IP 协议标准,这就是为什么不同操作系统的主机可以进行通信。

两台主机进行通信的结构如下图所示:

网卡是底层硬件,负责光/电信号的收发;数据链路层的功能由网卡驱动程序实现,通常运行在操作系统内核中;网络层和传输层也集成在操作系统内核中;应用层位于操作系统之上,由用户应用程序实现。

整个协议栈横跨硬件、驱动、操作系统内核和用户程序,因此其设计与实现需要 IT 行业各个层面的协同配合。

在网络通信中,传输层最著名的协议是 TCP,网络层最著名的协议是 IP。尽管操作系统不同(如 Windows 和 Linux),但它们的内核中都实现了相同的 TCP 和 IP 协议规范,以确保跨平台通信的可行性。正是因为 TCP 和 IP 是互联网中最核心的两个协议,这套协议体系被统称为 TCP/IP 协议


下面来看一张图:

主机B能识别data,并且准确提取a=10,b=20,c=30吗?当然可以,因为主机A与主机B之间的协议是相同的。尽管操作系统不同(如 Windows 和 Linux),但它们都实现了相同的协议规范。双方都定义了相同的结构体类型 struct protocol,并且该结构体的字段顺序、大小、对齐方式一致。当主机A将结构体序列化为字节流发送出去时,主机B可以根据相同的结构体定义反序列化,从而正确读取 a、b、c 的值。这说明:协议的核心之一是双方对数据格式的共识。在内核或驱动层面,这种共识常通过共享的结构体实现。对于协议的朴素的理解:从编程角度看,协议就像是一个通信双方都认识的结构体

举一个例子:在网上购物,买了一个商品A。当我们接收到快递时,不仅仅只有商品A,还有包装它的包裹,包裹上粘贴了一个快递单。快递单上写了始发地、目的地、收件人姓名、电话号码等信息。我们需要的是商品A,但最终收到的是“商品A + 快递单”。快递员怎么知道这个快递要送到哪里?如果送到了怎么联系收件人?答案就在快递单上!为什么快递单上有这些信息?因为这是寄件人、快递公司和收件人之间事先约定好的规则——这正是“协议”的本质。


协议栈是分层的,每一层在通信双方都实现了相同的协议规范。

虽然数据在物理上是逐层向下封装、通过底层传输、再逐层向上解封装,但从逻辑上看,每一层都“认为”自己在与对端的同层直接通信。

在操作系统内核的实现中,每一层的协议头部通常被定义为一个结构体(struct),用于描述该层控制信息的格式。

例如:

strcut ethhdr 结构体:

struct ethhdr {
    unsigned char   h_dest[ETH_ALEN];   /* destination eth addr */
    unsigned char   h_source[ETH_ALEN]; /* source ether addr    */
    __be16      h_proto;        /* packet type ID field */
} __attribute__((packed));

struct iphdr 结构体:

struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
    __u8    ihl:4,
        version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
    __u8    version:4,
        ihl:4;
#else
#error  "Please fix <asm/byteorder.h>"
#endif
    __u8    tos;
    __be16  tot_len;
    __be16  id;
    __be16  frag_off;
    __u8    ttl;
    __u8    protocol;
    __u16   check;
    __be32  saddr;
    __be32  daddr;
    /*The options start here. */
};

struct tcphdr结构体:

struct tcphdr {
    __u16   source;
    __u16   dest;
    __u32   seq;
    __u32   ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
    __u16   res1:4,
        doff:4,
        fin:1,
        syn:1,
        rst:1,
        psh:1,
        ack:1,
        urg:1,
        ece:1,
        cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
    __u16   doff:4,
        res1:4,
        cwr:1,
        ece:1,
        urg:1,
        ack:1,
        psh:1,
        rst:1,
        syn:1,
        fin:1;
#else
#error  "Adjust your <asm/byteorder.h> defines"
#endif  
    __u16   window;
    __u16   check;
    __u16   urg_ptr;
};

这些结构体定义确保了发送方和接收方对协议头的字段布局、大小端、位域顺序等达成一致,从而实现跨主机、跨操作系统的互操作性。

有了这种思想 —— 协议就是通信双方都认识的结构体,协议理解起来就很简单。操作系统中不仅仅只有一个协议,存在多个协议,OS是否需要管理这些协议?当然需要,如何管理?先描述,再组织。


5. 局域网网络传输的基本流程

如果两台主机连接在同一个局域网,那么它们可以直接进行通信。局域网通信的原理可以用上课点名来类比:老师喊“张三回答问题”,全班同学都听到了,但只有张三站起来回应,其他人则忽略这条信息 —— 因为“叫的不是我”。虽然这是老师与张三之间的一对一通信,但通信内容在教室中是公开的。

将这个场景映射到计算机网络:教室 = 局域网,每位同学 = 一台主机。要实现点对点通信,每台主机必须有一个唯一的身份标识,这个标识就是 MAC 地址。mac 地址是一个 48 位(6 字节)的地址,通常以十六进制表示(如 00:1A:2B:3C:4D:5E),理论上全球唯一。在通信时,发送方将目标主机的 MAC 地址写入数据帧;局域网内的所有主机都会收到该帧,但只有目标 MAC 匹配的主机会处理它,其余主机会丢弃。这种基于 MAC 地址进行目标识别的机制,是以太网(Ethernet)的核心特性之一。虽然 MAC 地址在网卡出厂时被固化,默认不可更改,但在操作系统中可以通过软件临时修改

Linux 机服务器也是一台电脑,那么它也有自己 mac 地址,使用指令 ifconfig 指令进行查看:

其中 ether 后显示的:fa:16:3e:fb:ea:dd 就是 mac 地址,共六个区域,每个区域8个比特位,所以一个mac地址共48个比特位。

使用指令 ipconfig /all 查看本台电脑的 mac 地址:

无线局域网适配器 WLAN 后显示的信息中,物理地址那行显示的信息就是 mac 地址。

理解了mac 地址后,主机A向主机E局域网内的通信如下图所示:

上图所示的过程是发生在数据链路层和网卡层中,上层对该过程0感知


如今我们知道局域网和以太网,那么局域网与以太网之间的关系是什么?局域网(LAN)是一个泛称,而以太网(Ethernet)是实现局域网的一种具体技术标准,定义了物理层和数据链路层的规范。在早期共享式以太网中,所有主机连接在同一总线上(如通过集线器 Hub),共享同一个通信信道。如果多个主机同时发送数据,就会发生信号冲突,导致数据损坏。因此,整个网络被称为一个碰撞域

为了检测冲突,每台主机在发送数据的同时会监听信道。如果某台主机发现接收到的信号与自己发送的不一致,就判断发生了冲突。只有正在发送数据的主机会进行冲突检测。检测到冲突后,主机立即停止发送,并执行特定的算法:随机等待一段时间后再重试;两次冲突后等待时间翻倍,以此减少再次冲突的概率。

在主机休眠期间,其他主机仍可发送数据。因此,局域网通信的本质是:基于碰撞检测和碰撞避免不断重试的过程。这个过程由数据链路层(网卡驱动)自动完成。

主机数量越多,同时发送的概率越高,冲突越频繁。因此,若持续向网络注入大量垃圾数据(如 DoS 攻击),会导致网络拥塞甚至瘫痪。

从另一个角度看待以太网,以太网不就是被所有主机共享的资源吗?而碰撞检测和碰撞避免的本质就是维护共享资源在任意时刻被一台主机使用,那么可以将以太网想象成一个临界资源,那么每台主机就可以想成一个个线程。数据发生碰撞不就是数据发生覆盖吗?这就是以系统视角看待以太网。

除此之外,还存在其他局域网通信方式 —— 令牌环网(Token Ring)。在令牌环网中,只有持有“令牌”的主机才能发送数据。这个“令牌”可以类比为操作系统中的互斥锁,即只有获得锁的线程才能访问共享资源。因此,令牌环网是一种事先加锁的机制,避免了冲突的发生。


主机A为什么要给主机E传输数据?数据来源于用户,由用户触发网络通信动作(如输入消息、点击链接),从而启动底层的数据传输过程。网络间的通信本质是操作系统之间协议栈的通信。因此,我们可以像下图所示那样看待网络通信:

数据的收发由网卡硬件完成,而协议解析、路由选择等由操作系统内核中的协议栈处理。用户A向用户B发送数据 data,该数据必须贯穿整个协议栈。每经过一层,当前层都会为其添加一个协议头部(即结构体),这个过程称为封装

具体流程如下:

  • 应用层:将用户数据(如 "hello")作为有效载荷;
  • 传输层:添加 TCP/UDP 头部(含端口号、序列号等);
  • 网络层:添加 IP 头部(含源/目标 IP 地址);
  • 数据链路层:添加 MAC 头部(含源/目标 MAC 地址);
  • 最终由网卡发送出去。

用户B的网卡接收到数据后,从下到上逐层进行解包

  • 数据链路层:剥离 MAC 头,检查目标 MAC 是否匹配;
  • 网络层:剥离 IP 头,检查目标 IP 是否匹配;
  • 传输层:剥离 TCP/UDP 头,根据端口号决定交给哪个应用;
  • 应用层:提取原始数据并交给用户程序。

将数据从下往上逐层去除头部并传递给上层的过程,称为分用。

分用与解包的简化图如下所示:

总结:

  • 封装:数据从上到下,每层加头
  • 解包:数据从下到上,每层去头
  • 分用:根据头部信息将数据交给正确的上层进程

对于每层来讲,去掉每层添加的报头,剩下的就是有效载荷

如果将data添加的报文想象成以下那般的内存空间:

这个过程可以形象地理解为一次“入栈”和“出栈”的操作:发送端:每层加头,类似“压栈”;接收端:每层去头,类似“弹栈”。

虽然现实中并未使用真正的“栈”数据结构,但这种类比帮助我们理解协议栈的分层处理机制。正因为这种层层封装与解封的结构,我们将 TCP/IP 的层级结构称为协议栈

报头部分是对应协议层的控制信息(通常对应 C 语言中的结构体字段),我们称之为“报头”;除了报头之外的部分,称为“有效载荷”。因此,一个完整的报文由两部分组成:报文 = 报头 + 有效载荷

不同层的完整报文有不同的叫法:

  • 在应用层,我们称之为请求与应答
  • 在传输层,TCP 的报文称为数据段,UDP 称为数据报
  • 在网络层,IP 协议的报文称为数据报
  • 在数据链路层,以太网的报文称为数据帧

我们知道,协议在内核中通常被定义为一种结构体类型(如 struct iphdr),而报头则是结构体变量。用户A向用户B发送消息“hello”时,该数据首先被存入操作系统内部的缓冲区。然后依次经过各层处理,每一层都将其协议头写入缓冲区的前端,形成新的报文。这个过程在代码中表现为:将结构体变量的内容拷贝到缓冲区。如下图所示:

因此,封装的本质是:在当前层的有效载荷前添加本层的协议报头,并填充必要的控制信息


作为接收方,每层协议都需要解决两个关键问题:

1. 报头和有效载荷分离的问题

报头的结构体类型可能是固定长度的,也可能是变长的,那么将封装后的数据传输给用户B进行报头和有效载荷的分离,只需要定义一个指针指向缓冲区的头部,由于大家遵守的都是相同的协议,所以结构体变量都是相同的大小,计算出对应层的结构体大小,然后指针向后移动相应的大小,如此不就将报头和报文分离了吗?

2. 当前层的有效载荷向上分用给哪一个协议(分用问题)

各层可能承载多种上层协议,例如:

  • 数据链路层可承载:IP、ARP、RARP 等;
  • 网络层(IP)可承载:ICMP、IGMP、TCP、UDP 等;
  • 传输层可承载:HTTP、DNS、FTP 等(通过端口号区分)。

现在报文分用给数据链路层,将报头与有效载荷分离后,将当前层的有效载荷分用给上一层即网络层,网络层有多种协议,怎么知道这个有效载荷要交给哪个协议呢?(每个协议就是一个结构体,交给哪个协议就是将数据拷贝到哪个结构体中)。在封装时,发送方会在当前层报头中写入一个协议标识字段,用于指示上层协议类型。接收方正是通过这个字段决定如何分用,接收方解析该字段后,调用对应的协议处理函数,并将有效载荷传递给它。将报头和有效载荷分离的问题就是解包的过程,当前层的有效载荷向上分用给哪一个协议就是分用的过程。


6. 跨网络传输

要进行网络数据传输,需要解决主机定位和路由选择的问题,因此需要了解 IP 地址

IP 协议有两个版本:IPv4 和 IPv6。

IPv4 使用4字节,32个比特位来表示一个IP地址,最常见的形式是 xxx.xxx.xxx.xxx,称为点分十进制表示法。其中每个数字代表一个字节,取值范围为 0~255。

IPv6 使用 16 字节(128 位)表示一个地址,采用十六进制冒号分隔格式,如: 2001:db8::1,极大地扩展了地址空间。

 IPv6 和 IPv4 在原理上类似,IPv6 主要解决 IP 地址不足的问题,之后文中提到的 IP 地址都是IPv4 版本的,除非明确表示是 IPv6。

使用ifconfig指令可以查看自己云服务器的IP地址:

inet 后面显示172.31.14.1就是云服务器的IP地址。

使用指令 ipconfig /all 指令可以查看自己电脑的IP地址(win + R打开一个窗口,输入cmd)

无线局域网适配器 WLAN 后面的内容中 IPv4 后显示的就是当前电脑的 IP 地址。


IP 地址能够标识公网中唯一一台主机,IP 能够为我们解决主机定位和路径选择问题,可以以我们在学校中的学号来理解 IP 地址。

但是在前面不是提到过每台主机都有 mac 地址吗?既然存在 mac 地址,为什么还有存在 IP 地址,mac 地址和 IP 地址的区别是什么?需要知道的是每台主机都有 mac 地址和 IP 地址。为什么一台主机要配套两个地址呢?

以我们人来举例:最终目标是找一份满意的工作,起始目标是学习计算机编程。一开始学习C语言,后面学习C++,接着学习数据结构,其次再学习算法,操作系统,计算机网络,做项目以及学习一些开源工具等等。最终目标对应的就是 IP 地址,中间目标对应 每一跳的 MAC 地址。

总结:IP地址提供长远目标,是跨网络通信中路径选择的依据;mac地址是当下或下一跳地址,解决局域网转发的问题

为什么mac地址会一直在变化?因为跨网络的主机通信过程中,数据要经过一个或多个路由器。每次经过一个路由器,都会发生一次解包与重新封装的过程,而MAC 地址只在当前局域网内有效。数据从一台计算机到另一台计算机传输过程中,可能经过多个路由器。如下图所示:

左右两侧的局域网使用不同的数据链路层技术:左侧是以太网,右侧是令牌环网。

当数据从以太网传入路由器时:路由器接收以太网帧;剥离以太网帧头(即数据链路层报头);提取 IP 数据报(网络层数据);根据 IP 头中的目标地址查询路由表,决定下一跳;在发送到令牌环网前,重新封装一个新的数据链路层帧头(即令牌环帧头);使用令牌环网的 MAC 地址作为目标地址。因此,MAC 地址并不是“变化”了,而是每一跳都更换了目标 MAC 地址。

  • 第一跳:目标 MAC 是路由器的以太网接口 MAC;
  • 第二跳:目标 MAC 是服务器的令牌环网接口 MAC。

带上具体的IP地址来理解跨网络通信,如下图所示:

用户A 通过 主机A 向 用户B 的 主机B 通信。主机A 的 IP 地址为:192.168.2.2,主机B 的 IP 地址为:172.168.2.2,路由器连接两个局域网,配置两个网络接口,分别拥有 IP:左侧:192.168.2.1右侧:172.168.2.1。路由器在每个子网中使用 .1 作为 IP 地址,便于识别。

当主机A发送数据时,上层数据逐层封装至网络层。网络层发现目标 IP(172.168.2.2)不属于本地子网(192.168.2.0/24),因此不会直接发给局域网中的某台主机,而是发给默认网关(即路由器 192.168.2.1)。

数据继续向下交付到数据链路层:源 MAC:macA(主机A 的 MAC),目标 MAC:macL(路由器左侧接口的 MAC)。封装后的帧在局域网中广播(或交换机泛洪),所有主机都收到,但:其他主机发现目标 MAC 不匹配 → 丢弃;路由器匹配成功 → 接收并自底向上解包。

路由器的网络层提取出 IP 数据报,查看目标 IP(172.168.2.2),查询路由表后发现该地址属于其右侧接口所在的子网(172.16.2.0/24),于是将数据从网络层向下交付到右侧的数据链路层。右侧数据链路层重新封装帧:源 MAC:macR(路由器右侧接口的 MAC),目标 MAC:macB。

新帧通过右侧网卡发送。局域网中其他主机收到后,因 MAC 不匹配而丢弃,只有主机B接收。主机B 自底向上解包:数据链路层:剥离 MAC 头;网络层:检查目标 IP 是否匹配(172.168.2.2 == 自己的 IP);继续向上交付,最终用户B 收到数据。这就是跨网络传输。

显然上述的跨网络传输中,核心点就是数据在路由器处重新解包并封装。整个过程中,IP 数据报在网络层保持不变在网络层看来,发送方的网络层,路由器的网络层,接收方的网络层,收发的是同一种报文。但每一跳的数据链路层帧头都被替换——可能是以太网头、令牌环头等,取决于底层网络类型。


在互联网发展早期,存在多种独立的网络,包括早期的广域网(如 ARPANET)和后来兴起的局域网(如以太网、令牌环、FDDI)。这些局域网采用不同的标准、硬件和驱动程序,帧格式互不兼容,导致跨网络通信极其困难。要求所有厂商统一硬件标准几乎不可能。于是,计算机科学家提出一个经典解决方案:通过增加一层软件抽象来屏蔽底层差异。这就是 IP 协议(Internet Protocol)诞生的核心动因!

在 TCP/IP 分层模型中:

  • 网络层(IP)提供统一的逻辑地址(IP 地址)和路由能力;
  • 路由器收到数据帧后,剥离底层链路头(如以太网头),提取 IP 数据报;
  • 根据目标 IP 查询路由表,决定下一跳;
  • 在出口接口重新封装为适合当前链路的帧格式

因此,网络层之下的物理和数据链路层可以千差万别,但网络层及以上看到的是一个统一的“IP 网络”。这种“IP over Everything”的设计,使得互联网能够包容各种底层技术,成为全球互联的基础。路由器作为实现 IP 转发的核心硬件,是构建互联网的关键设备。

mac地址和IP地址的区别:

IP地址在整个路由过程中,一直不变(目前这样理解);mac 地址一直在变

目标 IP 是一种长远目标,mac 地址是下一阶段目标

目标 IP 是路径选择的重要依据,mac 地址是局域网转发的重要依据,mac 地址只在局域网中有效


IP 网络通信的宏观流程:

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐