计算机网络这门课,很多人学完第三章数据链路层就开始头大,因为到了第四章网络层,视野一下子从“两台设备之间怎么传帧”跳到了“成千上万个网络之间怎么互联”。这一章是所有网络工程师、DevOps、后端开发的必修课,也是期末考和考研408的兵家必争之地。我开始工作后回头看,才发现大学里背的那些IP地址分类、子网掩码、TTL之类的考点,其实全是真实排查故障时的地基。这篇笔记我打算按照自己复习和实战时整理的逻辑来写,重点放在IP协议与地址体系、数据报格式、ARP与ICMP、路由选择这几个核心块,尽量结合“谢希仁第五版”和“自顶向下”两套教材的讲法,让你既能应付考试,也能真正理解网络层在做什么。
这一篇是笔记(一),先把网络层的整体设计、IPv4地址体系、IP数据报格式、ARP和ICMP讲透。路由协议那块牵扯的算法比较多,我会放到笔记(二)里单独展开。
1. 网络层到底在解决什么问题
1.1 转发与路由:网络层的两个核心动作
我当年学网络层,最大的误区是把它理解成“一堆IP地址的规则”。后来做DevOps,排查跨机房访问、配置云上路由表的时候才意识到:网络层整天干的事,本质上只有两个——转发和路由。
转发是路由器收到一个数据报后,查自己的转发表,决定从哪个接口把它送出去。这个动作是局部的、逐跳的,每台路由器只负责“下一步”,不需要知道整条路径。路由则是全网范围内计算出一条可达的路径,相当于提前规划好“从A到B该怎么走”。两者一配合,数据才能从源主机一路传到目的主机。
我在排查一个服务超时问题时,就遇到过路由表和转发表不一致的情况。动态路由协议改了路由,但某台老交换机还在按旧转发表转发,导致流量走到一半就被丢弃。这种坑很隐蔽,因为你看接口状态、看链路都是正常的,最后抓包才发现是转发表条目过期了。
理解这两个动作的区别,对后续学习很重要。转发表怎么生成?路由算法怎么收敛?这些都是第四章后半段的内容,但你要始终带着“转发靠查表、路由靠算法”这个大框架去看。
1.2 两种教材的叙事差异,我建议你都看一眼
网上的学习资源很多,有人看谢希仁的《计算机网络》,有人看库罗斯的“自顶向下”,还有人拿王道的课程当主力。这三个体系我基本都过了一遍,我觉得没必要纠结谁好谁坏,因为它们的叙事逻辑完全不同,配合起来看反而效果最好。
谢希仁的传统讲法是从底层往上走,先讲物理层、数据链路层,再到网络层。这种顺序符合网络构建的历史轨迹,学的时候很清楚“为什么需要网络层”——因为光靠链路层,你没有办法在不同局域网之间传递数据。自顶向下则是从HTTP、DNS这些应用层协议倒推下来,看到应用需要什么样的网络服务,再去理解网络层怎么设计。如果你已经有Web开发基础,看自顶向下会很爽,因为很多问题是从浏览器发起请求开始的。
王道的课程更像是“考试驱动”,把考点、计算题、常考概念浓缩得很密集,适合期末冲刺和408复习。但这也就意味着它会把很多机制背后的“为什么”一笔带过。我的建议是:第一遍用自顶向下建立“网络在提供什么服务”的直觉,第二遍用谢希仁补细节,考前用王道过一遍题型。这样既不会觉得枯燥,也不会漏考点。
1.3 IP层的“尽力而为”到底是个什么承诺
网络层最核心的协议是IP,它给网络提供的是一个极其朴素的承诺:“尽力而为”。什么意思?就是IP层会尽最大努力把数据报送到目的地,但不保证不丢失、不重复、不乱序。
我第一次听“尽力而为”这四个字,觉得这算什么设计?后来工作里调试TCP流才知道,IP层的不靠谱其实是一种刻意为之的“简单”。因为网络层面对的链路是五花八门的,有些链路质量很高,有些链路会丢包,有的底层MTU还不同。IP协议必须把这些差异全部屏蔽掉,向上层提供统一的、最简单的服务模型。至于可靠传输,那是TCP干的事;实时性,那是应用层和传输层协商的事;安全,那是TLS的事。IP层就是一门心思把数据报往目的地送,不掺和别的。
这个设计思想,后来我理解成“分工明确”。网络层不管可靠性,恰恰是它最大的优点,因为一旦路由器和交换机开始做复杂的可靠性保障,全网性能就会急剧下降。数据报丢了,TCP会超时重传;数据报乱序,TCP会重排。IP层只需要保证“送出去”和“尽量送对地方”,这个边界就很干净。
2. IPv4地址体系:从分类编址到CIDR
2.1 分类编址的“历史遗迹”与它的致命问题
IPv4地址是32位的,理论上有2的32次方个,大约43亿个。当年设计者为了管理方便,把地址分成A、B、C、D、E五类。A类开头一位是0,B类开头两位是10,C类开头三位是110,D类开头四位是1110用于组播,E类开头是1111留作实验。判断一个地址是哪一类,看第一个字节的范围就行:1-126是A类,128-191是B类,192-223是C类。
这个设计在当时看很合理:网络规模不同,就给你不同大小的地址块。A类一个网络就有1600多万个主机地址,B类有6万多个,C类只有254个。但放到今天看,这种“一刀切”的分配方式是灾难级的。因为你一旦申请到一个B类地址块,哪怕内部只用了100个主机,剩下的6万多个地址别人也永远用不了。我在做机房规划的时候翻过老拓扑,发现很多单位就拿着一个B类地址硬撑,地址利用率低得惊人。
另一个问题是路由表膨胀。分类编址下,路由器需要维护大量A/B/C类网络的路由条目,互联网规模一大,路由表就失控了。虽然分类编址在1993年已经被CIDR取代,但很多教材和考试还是会讲它,因为它的历史背景能帮你理解“为什么后来会演变成CIDR”。我复习的时候是把它当成“破而后立”的故事来记的:分类编址破了,CIDR立了。
2.2 子网划分:从“网段”到“子网”的一次进化
分类编址的另一个痛点是没有“内部结构”的概念。A类地址拿下来,一个网络内部不管有多少部门、多少办公区,全都在一个平面里,广播风暴和路由管理会非常痛苦。于是出现了子网划分。
子网划分的本质,是从主机号里“借”出若干位作为子网号。比如一个C类地址192.168.10.0/24,原本主机号有8位。如果借2位给子网号,就可以分出4个子网,每个子网有2的6次方减2等于62个可用主机地址。借的位数越多,子网数越多,每个子网能放的主机就越少。
子网掩码是区分网络号、子网号和主机号边界的关键。写成二进制,网络号加子网号对应的位全是1,主机号对应的位全是0。很多人会在这个地方犯迷糊:为什么/26的掩码明明是255.255.255.192,256减192却等于64?其实是因为2的(32-26)次方等于64,也就是说每个子网块的大小是64个地址,网络地址和广播地址各占一个,实际可用62个。
我记得有一次帮朋友配置办公室路由器,他之前拿到的IP是192.168.1.130,子网掩码是255.255.255.224,又觉得“192.168.1.1不是同网段吗,怎么ping不通?”我算给他看:192.168.1.0/27,块大小是32,所以192.168.1.128到192.168.1.159是一个子网,而192.168.1.1在0-31那个子网里,两个根本不是一个网段,当然不通了。这就是子网划分在日常里最简单也最实用的例子。
2.3 CIDR:把路由表“揉”小的高明手段
CIDR(无类域间路由)是对分类编址的彻底革命。它抛弃了A/B/C类那套刻板的边界,允许任意长度网络前缀。表示方式也很直观:192.168.10.0/24,斜杠后面就是网络前缀长度。 /24意味着前24位是网络号,后8位是主机号。
CIDR带来的最大好处是路由聚合。如果某运营商持有203.0.64.0/21这个地址块,它可以拆成8个/24的子网分配给不同客户。对外通告的时候,运营商只要通告一条/21的路由,外部路由器不需要知道内部那8个子网的细节。这就大大缩小了全球路由表的规模。
在路由器上做最长前缀匹配,是CIDR下的关键操作:目的IP可能同时命中两条路由,比如一条是/16,一条是/24,路由器会优先选择前缀更长的/24,因为更具体的路由覆盖的范围更小、更精确。我配置云VPC路由表时天天遇到这个逻辑,比如默认路由0.0.0.0/0指向公网网关,但某一台机器的具体路由指向内网下一跳,那这台机器的流量走内网,其他流量走公网。你如果没理解最长前缀匹配,看到路由表里同网段有两条路由就会一脸懵。
2.4 NAT与私有地址:不够用就得“复用”
IPv4地址只有43亿个,但全球联网设备早就超过这个数字了。缓解地址枯竭的重要方案之一,是RFC 1918定义的私有地址段:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16。这些地址在公网上不可路由,只能在内网里用。
NAT(网络地址转换)让私有地址的设备通过一个公网IP访问互联网。最常见的是NAPT,家用路由器用的就是它:内网所有设备共享一个公网IP,路由器在转换时用不同端口号区分不同内网设备。从外部看,所有流量都来自同一个公网IP的不同端口。
NAT在家庭和企业网络中几乎无处不在,但它也带来了不少麻烦。比如内网服务器想被外部访问,就得配置端口映射;P2P应用在NAT后面会面临连通性问题。做运维的都知道,NAT后面排查问题很痛苦,因为源地址被改了,抓的包和实际发出的包对不上。从长远看,IPv6的大规模部署才是解决地址枯竭的根本出路。但短期内NAT仍然是最普遍的过渡手段,这部分考试经常考NAT转换表怎么填、私有地址范围是哪些,必须拿满分。
3. IP数据报格式:把首部字段逐个吃透
3.1 20字节必读字段逐个说
IPv4数据报分首部和数据两部分,首部最小20字节,最大60字节。前20字节是所有路由器必须解析的,后面的选项字段一般用不上。我复习时习惯把20字节首部按顺序背下来,因为考试常考字段位置,工作里抓包看协议时也能一眼定位关键信息。
版本字段占4位,IPV4取值为4。首部长度字段占4位,单位是4字节,所以如果值是5,首部就是20字节;如果值是15,首部就是60字节。总长度字段占16位,单位是1字节,表示整个IP数据报的长度,最大65535字节。
标识、标志、片偏移这三个字段是分片用的,我放到下一节具体讲。TTL占8位,每经过一台路由器减1,减到0就被丢弃,防止数据报在网络里无限循环。协议字段占8位,表示上层协议:ICMP是1,IGMP是2,TCP是6,UDP是17,这份对应关系面试经常问。首部校验和只校验首部,校验算法比较朴素:把首部按16位一组累加,取反码。路由器每收到一个数据报,TTL要减1,首部内容就变了,所以每跳都要重新计算校验和,这也是IPv4路由器性能开销的一个来源。
3.2 分片与重组:被边缘化但考试老爱出的知识点
链路层每个帧能承载的最大数据量叫MTU。常见以太网MTU是1500字节。如果一个IP数据报超过了MTU,且不允许分片,就会被丢弃并回送ICMP错误消息;否则就得分片。
分片的规则是这样的:每个分片都是一个独立IP数据报,有自己的首部;标识字段用来标记“这些分片属于同一个原始数据报”;标志字段里有三位,第二位DF(禁止分片),第三位MF(还有分片);片偏移的单位是8字节,表示该分片数据部分在原始数据报中的相对位置。
举个例子:假设要发送一个IP数据报,总长度2400字节,首部20字节,数据部分就占2380字节。以太网MTU 1500字节,每个分片首部20字节,实际能容纳的数据最多是1480字节。1480恰好是8的倍数,所以第一个分片数据部分1480字节,第二个分片数据部分也是1480字节,原始数据还剩下2380减1480减1480等于负的,不对,得算仔细点。2380减去1480等于900,所以第二个分片实际只装900字节,最后一个分片MF=0,片偏移是1480除以8等于185。三个分片的总长度分别是1500、920(20加900)……等等,我再重算一下:原始数据2380字节,第一片装1480,剩900;第二片装900,MF=0;所以两个分片就够。第一个分片总长度1500,第二个总长度920,片偏移分别为0和185。
分片只在路由器上发生,重组只在目的主机进行。原因很简单:中间路由器不知道后续路径的MTU,让所有分片到终点再组装,效率最高,也不会因为某条链路MTU更小而反复分片。但分片的坑在于:其中一个分片丢了,整个数据报都要丢弃,因为重组不了。所以现在很多链路层协议、TCP分段、IPv6都尽量避免中间分片,而靠源端的路径MTU发现来解决。
3.3 为什么IPv4只校验首部不校验数据
很多刚学的人会问:IP首部有校验和,为什么数据部分不校验?答案是:IP层不承诺可靠传输,数据部分是否正确,由上层协议负责。TCP每个报文段有校验和,UDP也有一个可选的校验和。网络层只要保证“首部信息无误”就已经尽了本分,再给数据做校验只会拖慢转发速度。
到了IPv6,连首部校验和都取消了,因为传输层都会做端到端校验,链路层也有FCS之类的检错机制,再做一层纯属浪费。这个演化过程提醒我们:网络协议的每一层都在做“最小必要的事”,不要把上层和下层的职责都揽到自己身上。
4. ARP与ICMP:让IP真正跑起来的两个配角
4.1 ARP:从IP到MAC的翻译官
IP地址是逻辑地址,MAC地址是物理地址。在一个局域网内,主机A想给主机B发数据,A知道B的IP,但不知道B的MAC地址,因为帧的封装需要目的MAC。这时候就要靠ARP(地址解析协议)。
ARP的工作流程是:A在本网段内广播一个ARP请求,内容是“谁的IP是x.x.x.x?请把MAC地址告诉我”。同一网段所有主机都能收到这个广播,但只有IP匹配的那台主机应答,并且应答是单播的,内容是“我是x.x.x.x,我的MAC是yy:yy:yy:yy:yy:yy”。A收到应答后把IP和MAC的对应关系写进ARP缓存,下次直接查表,不再广播。
不过ARP是3层协议还是2层协议,不同教材说法不一。谢希仁把它归在网络层,自顶向下把它当作链路层的一部分。实践中抓包时你会看到ARP报文直接封装在以太网帧里,没有IP首部,所以我更倾向把它理解成“连接3层和2层的胶水协议”。
ARP缓存有老化时间,默认一般是几分钟到几十分钟不等。运维中遇到“ping得通网关但ping不通另一台机器”时,清ARP缓存是标准操作之一。Windows用arp -d,Linux用ip neigh flush或arp -d,然后重新探测。
4.2 ARP欺骗:为什么免费ARP不一定是好事
ARP协议从设计上就有安全缺陷,因为它不验证请求来源。局域网里任何一台主机收到ARP请求后都可以应答,不需要确认自己是否真的是该IP的持有者。这就导致了一种经典攻击——ARP欺骗:攻击者发送虚假的ARP应答,把网关IP绑定到自己的MAC地址,于是原本发给网关的流量就全部经过攻击者。
我实习时参与过校园网的稳定性维护,有段时间某栋宿舍楼频繁掉线,排查发现就是有人开了ARP欺骗工具,全网终端都在往错误MAC回包。解决办法是在交换机上做IP-MAC绑定,或者启用动态ARP检测(DAI)。对个人用户来说,用静态ARP表能防住部分欺骗,但在大网里手动绑几千个IP也不现实。这个知识点在面试和日常运维里都挺重要,值得多了解。
4.3 ICMP:ping和traceroute都靠它
ICMP(互联网控制报文协议)是IP协议的配套协议,用来传递差错报告和网络诊断信息。它不是一个“传输数据”的协议,而是网络管理员的耳朵和眼睛。
最常用的就是ping命令,它发送ICMP回显请求(类型8),目的主机会返回ICMP回显应答(类型0)。如果链路某个环节出现问题,你还可能收到“目的主机不可达”(类型3),或“TTL超时”(类型11)。比如配置了防火墙禁ping,你收到的就是类似于“管理性禁止”的ICMP报文,这在排查时能直接告诉你问题性质。
traceroute的原理也很有意思。它利用TTL过期机制,先发送TTL=1的UDP报文,第一跳路由器发现TTL减到0,就回一个ICMP超时消息;再发TTL=2,第二跳的IP地址就暴露了……这样一路下去,整条链路路径就展现在你眼前。我排查跨机房延迟时候经常用mtr(结合ping和traceroute的工具),哪一跳延迟飙升、哪个节点丢包,一目了然。DevOps和运维手里一定要有这些武器的使用经验。
5. 路由选择:路由器怎么决定往哪走
5.1 静态路由和动态路由,用一时还是用一世
路由表可以手动配置,这就是静态路由。在小型、拓扑稳定的网络里,静态路由简单高效,没有协议开销,也不会被路由更新风暴干扰。我配置过几台三层交换机,就三四个网段,静态路由写几条就完事,稳得很。
但网络规模一大,手动维护就不现实了。链路故障、拓扑变更时,静态路由不会自动适应,所有路径都得人工改。于是有了动态路由协议。路由器之间通过协议交换网络可达性信息,自动计算最优路径,链路断了就重新收敛。动态路由对运维的解放是巨大的,代价是需要学习和理解协议本身。
选择方案时要结合网络规模:家庭、小型办公网络,静态路由或默认路由就够;中型企业网,OSPF是最稳妥的选择;跨运营商、跨自治系统的骨干,则必须用BGP。不要一上来就想着上BGP,那是在给自己找麻烦。
5.2 RIP用距离向量:教材里的“活化石”
RIP(路由信息协议)是最早的一批动态路由协议,属于距离向量算法。它的思想很朴素:每个路由器只告诉邻居“我这边能到哪些网络、距离是多少跳”,距离以跳数为单位,最大15跳,16跳视为不可达。
RIP的优点是实现简单,但问题也很明显:收敛慢,遇到环路的收敛时间可能几十秒甚至几分钟;以跳数为唯一度量,不考虑带宽和延迟,选出来的路径往往不是最合理的。现代网络中RIP基本被淘汰了,但考试会考它的协议细节,比如UDP端口520、更新周期30秒、路由毒化等机制。我学RIP的最大收获不是会用,而是理解了“分布式计算距离信息”的基本模型,这在理解后续更复杂的协议时非常有帮助。
5.3 OSPF用链路状态:现代内网的主力
OSPF(开放最短路径优先)属于链路状态算法,它的思路和RIP完全不同。每台路由器通过洪泛机制把自己的链路状态(连接了哪些邻居、链路开销是多少)发给区域内所有路由器,每台路由器最终收到整个区域的完整拓扑图,然后用Dijkstra算法计算到各网段的最短路径树。
对比之下,OSPF的收敛速度、路由选择的准确性都远胜RIP,而且支持区域划分,适合中大型企业网络。代价是配置和维护复杂度高:要规划区域、要设计Router-ID、要处理DR/BDR选举等。我在一些稍微正式的园区网项目里用的就是OSPF,配完多区域后整体效果很稳定。
学OSPF要抓住两个关键词:SPF算法和区域。所有路由器维护相同LSDB(链路状态数据库),计算路径用SPF;区域设计把网络拆小,控制洪泛范围,让协议更可控。考试里的OSPF题型大多是给一个拓扑,让你写出DR/BDR是谁、区域内路由条目怎么算,理解了SPF树的构建过程就基本拿下了。
5.4 BGP:自治系统之间的“外交官”
当网络规模上升到运营商和云厂商的骨干级别,路由选择就不再单纯以“最短路径”为目标,而是涉及大量商业策略。BGP(边界网关协议)登场,它在自治系统(AS)之间交换路由信息,路径属性里带有AS路径、本地优先级等多种策略参数。
很多做应用层开发的同学看到BGP就觉得和自己没关系,其实R有的业务也会碰到。比如你买了云厂商的多线BGP带宽,其实就是在利用BGP网络的能力,让不同运营商用户访问到最优路径。跨地域服务架构中,公网入口选择哪条链路、什么回程,都和BGP的路由策略息息相关。
BGP我建议初级学习者先记概念:EBGP在AS之间用,IBGP在AS内部用;AS_PATH越长越不优;BGP基于TCP 179端口,所以它是可靠的。细节的路由反射、联盟这类机制,等真做运营商或大型网络的运维再去深究也不迟。
6. 写给期末复习和工程师实践的三件事
6.1 经典题型速览:会算这几个就算过关
期末考得最密集的题型我整理了一下:第一是IP地址分类与判断,给你一个地址问是哪一类、网络号主机号各多少;第二是子网划分,给一个网络要求划分成若干子网,计算出每个子网的网络地址、广播地址、可用主机范围;第三是CIDR聚合,把几个连续地址块合并成一个前缀;第四是IP数据报分片,给一个总长度和MTU,算出分片数量、每片的总长度、标识、片偏移和MF标志。第五是ARP与ICMP概念题,问ARP流程、ICMP报文类型。这些计算题套路固定,你只要把“块大小 = 256 - 掩码”这个公式吃透,再配上二进制换算,基本能保住20分以上。
我复习时做了一个小表格:
| 位置关系 | 计算方式 | 实例(192.168.1.66/26) |
|---|---|---|
| 网络地址 | IP 与掩码相与 | 192.168.1.64 |
| 广播地址 | 子网块最后一个地址 | 192.168.1.127 |
| 可用主机范围 | 网络地址+1 到 广播地址-1 | 192.168.1.65~126 |
| 可用主机数 | 2^(32-前缀) - 2 | 62 |
6.2 教材与课程的搭配方案
如果你时间充裕,我建议的学习路径是:先看“自顶向下”的网络层章节,建立整体直觉;再用谢希仁的教材补协议细节和中文术语表;考前几天用王道/湖科大教书匠的课过一遍重点和易错点。我的体验是,谢希仁的教材术语比较规范,考试答名词解释题很有优势;自顶向下的例子尤其是“跟着数据报走一遍”的章节图,能帮你把协议栈串起来。
湖科大教书匠的课程比较适合初学者,讲得很细,每一步都用动画推演,特别是IP分片和路由协议那块,动画效果比看书容易理解十倍。至于“适合考408吗”这个问题,我的看法是:课程能帮你理解,但408的坑多在“题目综合性强”和“花式计算”,最后还是得靠刷题。
6.3 一点实践建议:把网络命令变成肌肉记忆
不管你是准备考试还是做DevOps,光背协议字段是没用的。我的建议是打开命令行,把下面的操作练成肌肉记忆:ipconfig或ip add看自己的地址和网关;ping -n 1 -w 100或ping -c 1 -W 1测连通性和延迟;tracert/traceroute/mtr看路径每一跳;arp -a看ARP缓存;netstat -rn或route -n看路由表。我面试候选人时,聊到网络排查,如果对方能顺手敲出这些命令并解释输出含义,分数就很高。
学第四章不需要死记硬背每一个字段在哪个字节位置,但核心思想一定要牢:IP层向上提供尽力而为的数据报服务,向下要适配各种异构链路;地址体系完成了从分类到CIDR的演进;路由表是路由器转发的基础;ARP和ICMP是IP协议的左右手。搞懂这些,你对网络层的理解就比单纯背教材高出一个段位了。