再看上面这幅图,从网络层(IP 层)视角来看,发送方发送的、路由器路由的、接收方收到的 IP 报文都是一样的** ,报文的源 IP 与目的 IP 全程不变,IP 报文本身也不会被修改;但到数据链路层时** ,每经过一段局域网或一台路由器,MAC 地址头部都会被解封装、重新封装------ 源 MAC、目的 MAC 会随链路不断更换,底层甚至可能一边是以太网帧、另一边是令牌环网帧,链路层格式完全不同。
这正是网络 IP 层最关键的作用:网络 IP 层能屏蔽底层数据链路层的差异。无论底层局域网是以太网、令牌环网还是其他局域网,网络层的 IP 报文格式始终统一,上层只需关注 IP 寻址与路由,不用关心底层链路的具体实现,真正实现了跨异构网络的互联互通。
再看上面这幅图,网络的真实通信场景如上图 : 用户 A 发出的数据,会自上而下经过本机应用层→传输层→网络层→数据链路层 ,由网卡发出;随后经过多台路由器逐跳转发 ------ 每台路由器都会在数据链路层解封装、网络层查询路由、再重新封装数据帧发往下一跳;最终数据抵达用户 B,自下而上逐层解包,交付给上层应用。整条链路中,每一段局域网可以是不同类型的链路技术,全程由 IP 协议统一调度。
所以我们能得出下面两个结论 :
结论 1:底层链路差异,对上层编程完全透明
无论底层局域网是以太网、无线 LAN、令牌环网,站在网络 IP 层、传输层、乃至应用层 的视角,通信行为没有任何区别。也就是说上层应用只需要通过 Socket 套接字、Linux 系统调用 发起网络请求,只需要指定目标 IP 与端口,不需要关心底层是网线、WiFi 还是其他老式局域网技术。操作系统内核会自动完成 IP 报文与不同链路帧的封装、转发,底层差异完全被内核屏蔽,因此我们编写网络程序时,无需区分底层硬件与链路类型,一套 Socket 代码就能适配所有网络环境。
结论 2:手机与电脑跨链路通信的本质
比如现实生活中手机能和电脑通信,手机是无线 WiFi (无线 LAN) 的,电脑是以太网,二者能通信的核心原因是双方都遵循统一的 IP 协议 。以太网与无线 LAN 只是数据链路层的不同实现,IP 层会统一封装数据:电脑发出的 IP 报文被封装为以太网帧,经路由器转发后,到达手机所在局域网时,会被重新封装为无线帧;全程 IP 报文格式、寻址规则保持一致。正是 IP 协议抹平了有线与无线的底层差异,让异构设备可以互联互通。
(1). 任何一台主机都隶属于某一个局域网(2). 任何一台主机想要接入网络上网,内部必须配备网卡;每一块网卡在出厂时,都会内置一个 48 比特位 (6 字节) 的 MAC 地址,用来标识这台主机在当前局域网内的唯一身份。
什么是 MAC 地址?
MAC 地址本质是数据链路层中用于识别相邻网络节点的硬件地址, 标准长度为 48 位、共 6 字节,日常以十六进制 + 冒号的格式表示,例如 08:00:27:03:fb:19。
MAC 地址的核心特点是:地址在网卡出厂时就已固化写入硬件,理论上全球唯一;仅在当前局域网内生效,无法跨网络传递,经过路由器转发时会被重新封装修改。需要补充的是,虚拟机的虚拟 MAC 并非真实硬件地址,存在冲突可能,部分网卡也支持手动修改 MAC 地址。
对比理解MAC地址和IP地址
我们可以通俗对比 MAC 地址与 IP 地址:IP 地址描述的是端到端通信中,整条传输路途的总起点与总终点 ,全程保持不变,负责跨全网寻址;而 MAC 地址描述的是传输路径上,每一段局域网链路的起点与终点,只在单段局域网内有效,每经过一台路由器、一段链路就会发生改变。二者分工配合,共同完成互联网的数据传输。
很多人都会混淆 MAC 地址和 IP 地址都是用来标识主机唯一性的,那它们到底有什么区别?
首先,MAC 地址只保证局域网内唯一。它是网卡出厂自带的硬件编号,只在家、办公室这一小片局域网里生效,交换机靠它找设备;一旦数据跨路由器、跨网络,MAC 地址就会被不断改写,因此 MAC 地址出不去当前的局域网。
而 IP 地址保证全网范围内唯一。它不是硬件自带的,是网络分配给主机的逻辑地址,能跨越路由器、跨越整个互联网,用来定位端到端的起点和终点------ 也就是从你电脑,到地球另一端服务器的完整地址,全程不会变。
之所以互联网必须同时有这两个地址,是因为分工不同:
IP 地址负责宏观指路 :告诉数据 "最终要从 A 主机到 C 主机",解决跨网络、跨广域网的寻址问题;
MAC 地址负责微观跑腿 :在每一小段局域网里,告诉数据 "这一跳要发给哪个网卡",解决局域网内部、直连设备之间的交付问题。
我们可以通过系统命令直观看到设备的 MAC 地址:在 Windows 中执行网络查询,会显示物理地址,这正是网卡的 MAC 地址,图中为 1C-83-41-CF-BE-32,以短横线分隔;而在 Linux 中使用 ifconfig 命令,会通过 ether 字段展示 MAC 地址,上图中云服务器的 MAC 地址为 52:54:00:0f:f8:8a,以冒号分隔。
二者本质完全一致,只是系统展示格式不同:Windows 习惯用短横线分隔,Linux 用冒号分隔,都代表对应网卡的 48 位硬件 MAC 地址,用于在局域网内标识设备身份。
认识MTU
MTU(最大传输单元)本质是数据链路层对单次传输数据包大小的硬性限制,可以理解为快递对包裹尺寸的上限规定,不同链路标准的 MTU 各不相同。
当 IP 报文长度超过当前链路 MTU 时,IP 协议必须对数据包分片 :把大 IP 包拆成多个小包,给每个分片打上相同标识、分片标记,到达接收方后再按顺序重组还原。需要注意,IP 分片后任意一个小包丢失,整体重组就会失败 ,而 IP 层本身不负责重传,重传要依赖上层 TCP 协议完成。也正是因为 MTU 带来的分片需求,IP 协议才设计了4 位首部长度、16 位总长度字段,用来标识 IP 头大小与完整数据包长度,实现分片与重组。
在 Linux 系统中执行ifconfig,我们能直接看到网卡mtu 1500,就是以太网的这个上限值。
四、局域网通信原理
以太网通信原理(传统共享式以太网)
以太网的通信,本质限定在同一个局域网内部。如上图,比如主机 A 向主机 E 发送数据时,数据会被封装成以太网帧(MAC帧)并广播发送到整个局域网 ,局域网内的所有主机 (主机 B、C、D、E) 都会收到这一帧数据。每台主机收到数据帧后,都会读取帧头中的目的 MAC 地址进行判断:如果目的 MAC 和自身网卡的 MAC 地址一致,就收下数据并向上层交付;如果不一致,就直接丢弃该帧。正因如此,我们看起来像是只有主机 A 和主机 E 在一对一通信,但实际是数据被全网广播、其他主机自动过滤丢弃,才形成了 "点对点传输" 的错觉。
混杂模式与局域网抓包:
在正常局域网通信中,主机收到以太网帧后,会核对目的 MAC 地址 ,不是发给自己的报文就会丢弃。而混杂模式 是网卡的一种特殊工作模式:开启后网卡不再校验目的 MAC 地址,局域网内所有广播过来的报文,无论目标是谁,都会直接接收并向上层交付。此时如果有黑客控制了一个主机并开启混杂模式,就能捕获局域网内所有传输数据,实现抓包监听,这也是局域网环境中常见的网络窃听风险。
为了解决主机增多带来的碰撞拥堵问题,我们引入了交换机,正式进入现代交换式以太网时代。交换机工作在数据链路层,核心作用是划分碰撞域 :交换机的每一个独立端口都是一个单独的碰撞域。当主机 A 向主机 E 发送数据时,交换机会读取帧中的目的 MAC 地址,只把数据精准转发到目标主机 E 所在的端口,不会广播给其他所有主机。
交换机刚上电,也就是刚启动时,交换机内部是没有任何主机的信息的(MAC 地址表是空的)。交换机不知道各个主机的 MAC 地址分别对应哪个端口。比如当主机 A 要给主机 E 发送数据帧时,帧里会明确标注源 MAC 地址MacA、目的 MAC 地址MacE。数据到达交换机后,交换机会先读取源 MAC 地址 MacA,立刻在自己的 MAC 地址表里记录:MacA → 左侧eth_left端口,完成一次地址记录。但此时交换机查表,找不到 MacE 对应的端口,它开始是不知道主机 E 连在哪个口。这种情况下,交换机无法精准转发,只能执行泛洪(广播转发):把这份数据帧,向除了来源端口之外,所有其他端口全部复制发送出去。也就是除了 A 所在的左侧端口,右侧所有端口都会收到这份数据,这就是泛洪。
泛洪之后,右侧的主机 E 收到数据,识别到目的 MAC 是自己,接收并处理;其他主机识别 MAC 地址与自己不符,就直接丢弃。之后主机 E 要回复主机 A,回复帧的源 MAC 变成 MacE、目的 MAC 变成 MacA。这份回复帧进入交换机后,交换机再次做地址学习:记录MacE → 右侧eth_right端口。
随着局域网里每台主机收发数据,交换机都会不断学习,慢慢把 MacB、MacD、MacC 等所有 MAC 地址和对应端口都记进 MAC 地址表。后续比如主机 A 和主机 C 通信时,交换机查表发现:MacA 和 MacC 都在左侧端口,于是只在左侧端口内部转发,就不会再往右侧端口发送;如果是左右跨端口通信,就只连通对应的两个端口,不再全网泛洪。
这里要注意的是,主机 A、B、D 全部都接在交换机同一个左侧端口 eth_left,主机 C、E 接在同一个右侧端口 eth_right。因为交换机的规则是同一个物理端口下的所有设备,共享同一个碰撞域;只有不同端口之间才互相隔离碰撞域。所以主机 A、B、D 都在左侧 eth_left 这同一个碰撞域里:如果 A 和 B 同时发消息,就会在这条链路上发生数据碰撞;同理,右侧端口下的主机 C 和 E 同时发消息,也会在右侧链路里产生碰撞。但左右两侧端口之间是完全隔离的,左侧 A、B 通信产生的碰撞,不会影响右侧 C、E 的通信;两边可以同时传输数据、互不干扰。只有当我们把每一台主机都单独接交换机的一个独立端口,每台设备独占一个碰撞域,才能避免碰撞。