
干了几年后端说实话最怕的不是业务逻辑写出bug而是线上突然来一句“接口超时”“连接被拒绝”“数据库连不上了”。这时候你翻日志代码层面一切正常问题几乎都卡在网络链路上的某一环。每次被这种问题折磨完我都会重新翻一遍计网知识点——这套东西平时躺在教科书里显得很理论真到排查现场就成了救命地图。所以我想把这些年在实际中用得上的计算机网络知识做一个系统梳理从OSI分层、IP子网划分到TCP的握手和可靠性机制再到HTTP、DNS这些每天打交道的应用层协议最后收在排查实战上。不管是正在准备面试的读者还是跟我一样偶尔要和交换机、路由器、抓包工具较劲的同行这份知识点清单应该都能直接用上。1. 先搭一张地图计网知识体系的整体框架1.1 为什么所有网络问题都可以先归到某一层很多初学者学计网最痛苦的地方是不知道从哪儿看起。教材先讲物理层、数据链路层第二页就开始讲曼彻斯特编码看了三天还在底层打转完全看不到全貌。我的建议是反过来先把OSI七层的名字和作用记牢再把TCP/IP四层作为实际工作的主线之后所有知识都往这张地图上挂。OSI七层从下到上依次是物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。这里值得强调的是会话层和表示层在现实世界的协议栈里基本被融合进应用层了所以实际使用的TCP/IP模型只有四层网络接口层、网络层、传输层、应用层。面试时如果被问“TCP/IP四层和OSI七层的对应关系”核心考点就在这两层“消失”了以及网络接口层对应了OSI的物理层和数据链路层。为什么要分层我用寄快递来打比方。你写好的信应用层数据不会被直接扔进邮车而是要先装进信封写上收件人和地址这一层相当于网络层加IP头部再贴上快递单号传输层端口最后装进快递袋链路层加MAC头部。每一层只关心自己的那一层封装不需要知道上层内容是什么。网络分层解决的是“复杂问题拆解”的问题每一层只需要和上下层通过固定接口对接内部怎么实现是自由的。这就带来一个实际好处——排查网络故障时可以按层缩小范围。物理层丢包就往网线、光纤上查链路层问题看MAC地址、ARP网络层问题查IP路由传输层问题查端口、连接状态。这个分层思维是整套计网知识的骨架没有它后面所有细节都只是零散碎片。1.2 数据包封装与解封装一次请求完整走过的路理解了分层下一步要看数据在每一层是怎么处理的。这里有个关键词叫“封装”。比如你发起一个HTTP请求应用层先构造一个HTTP报文包含请求行、请求头和请求体。传到传输层TCP会把这个报文当成自己的载荷在它前面加上TCP头部里面最重要的是源端口和目标端口——端口号决定了这个数据到了对方机器后交给哪个进程。继续往下进入网络层IP协议加上IP头部里面最重要的就是源IP和目标IP这一步决定了数据怎么从一台机器路由到另一台机器。最后到网络接口层加上以太网头部包含源MAC地址和目标MAC地址尾部还有校验字段这就是一帧。接收方做的动作是反向的叫解封装每层剥掉对应的头部把载荷向上交给更高层。这个“套娃”过程是整个计网数据流动的核心几乎所有的协议抓包内容本质上都在展示这个过程。我为什么花这么多篇幅讲封装因为很多面试题和实际排查场景都会落到这里。比如你问“为什么网络抓包看不到HTTP内容只能看到TCP报文”因为数据在传输层已经被加密或者被分段了只有重组之后才能看到应用层内容。再比如“MTU是什么”就是网络接口层一帧能承载的最大载荷超过这个值IP层就要做分片分片之后遇到防火墙某些设置还会被丢弃这类问题是网络性能优化里的经典坑。1.3 用抓包把抽象概念变成可见的信号只看理论和图解计网知识很容易记成死背。我自己的转折点是开始用抓包工具之后——所有抽象概念都被展开了TCP握手变成了一条条带标志位的报文DNS查询变成了一次次请求响应。常用的抓包工具就是Wireshark和tcpdump。Wireshark适合图形化分析tcpdump适合在服务器上命令行抓包。一个最基础的用法是这样# 抓取本机所有HTTP流量不解析域名保存到文件 tcpdump -i eth0 tcp port 80 -w http.pcap # 抓取某个IP的所有进出流量 tcpdump -i eth0 host 192.168.1.100 # 抓TCP三次握手包只看SYN和ACK标志 tcpdump -i eth0 tcp[tcpflags] (tcp-syn|tcp-ack) ! 0抓包的意义在于帮你建立验证感。书上说“TCP三次握手”你抓一次包亲眼看到SYN、SYN-ACK、ACK三条报文就再也不会忘。说“DNS用UDP 53端口”你自己发一个nslookup指令再抓包看到一条条UDP查询记忆会非常牢。我建议学计网知识点的人不要纯刷题每个关键协议都实际抓一次包效率会高很多。2. 硬骨头IP地址与子网划分2.1 IP地址结构网络位和主机位决定了一切IP地址是整个网络层最重要的基础。IPv4地址是32位的二进制数表示成点分十进制比如192.168.1.10。这个地址看起来只是四组数字其实内部被分成两部分网络位和主机位。网络位标识设备所在的网络主机位标识网络内的具体设备。这个概念是子网划分的前提。知道怎么区分网络位和主机位靠的是子网掩码。比如255.255.255.0这个掩码二进制是连续的24个1加8个0说明IP前24位是网络位后8位是主机位。网络位的价值在于路由寻址——路由器在转发数据包的时候只看目标IP的网络位不看主机位就能确定应该往哪个方向转发。这就像快递员送件只看城市名一样不需要知道每条街每个门牌号先送到城市节点再说。额外的常见考点是IP地址分类。A类地址范围是1.0.0.0到127.255.255.255默认掩码是8位B类是128.0.0.0到191.255.255.255默认掩码16位C类是192.0.0.0到223.255.255.255默认掩码24位。还有三个特殊的地址段要记牢127.0.0.0/8是回环地址本机自己访问自己用数据根本不会出网卡169.254.0.0/16是链路本地地址DHCP分配失败时系统会自动拿一个看到这种IP基本可以判断网卡没拿到IP224.0.0.0/4是组播地址。2.2 子网掩码和CIDR的实际计算面试和实际配置里逃不掉的是CIDR和子网计算。CIDR的表示法很简单就是在IP后面加个斜杠写上网络位的个数比如192.168.1.0/24意思是前24位是网络位。这时候你看到一个IP地址要能快速算出它的网络地址、广播地址和可用主机范围。我平时用的计算思路是这样的先看斜杠后面的数字n主机位就是32-n位可用主机数量是2^(32-n)-2减掉的2个分别是网络地址和广播地址网络地址就是把IP的主机位全部置0广播地址就是把主机位全部置1举个例子192.168.1.66/26。n26主机位6位所以可用地址数是2^6-262个。这个地址属于哪个子网把66转成二进制是01000010前26位是网络位后6位是主机位所以网络位最后的两个bit是01也就是说这个IP所在的子网是从192.168.1.64开始的网络地址是192.168.1.64广播地址是192.168.1.127可用范围是192.168.1.65到192.168.1.126。这个计算不用手算也行服务器上装个ipcalc一行命令就出结果ipcalc 192.168.1.66/26 # 输出会直接给出Network、Netmask、Broadcast、HostMin、HostMax但考试和面试时不一定让你用工具所以手算的套路还是要熟。我的经验是把2的幂次背熟2^82562^71282^6642^5322^416。多数场景下只需要和这几个数打交道。2.3 私有地址、网关和路由配置网络时的三个关键点搞清楚了地址计算还要知道哪些地址能用在公网上哪些只能在内网用。RFC 1918规定了三个私有地址段10.0.0.0/8、172.16.0.0/12、192.168.0.0/16。这三个段在公网上不会被路由专门给内网使用。家里路由器默认网段192.168.1.0/24就是私有地址段的典型例子。实际配网络的时候有四个东西必须配对IP地址、子网掩码、网关、DNS。IP和掩码决定了你属于哪个网络网关是你的数据发往其他网络的出口DNS负责把域名解析成IP。我碰过不少案例用户说“上不了网”排查下来IP和掩码都对网关ping不通最后发现是网关IP写错了一个数字。排查这类问题记住一句话就够了先看本机网卡是否up再看IP掩码网关是否匹配最后ping网关、ping公网IP、ping域名逐层定位。3. 传输层TCP是怎么做到“靠谱”的3.1 三次握手不是三次打招呼而是一套状态同步机制TCP被誉为“可靠传输”的基石而三次握手就是它建立连接的方式。很多人把三次握手理解为“你好了吗”“我好你呢”“我也好”这个比喻够亲切但不够精确。三次握手的真正作用是同步双方的初始序列号。客户端先发一个SYN报文把自己的序列号设为x同时进入SYN_SENT状态。服务端收到后回复SYN-ACK报文确认号是x1同时把自己的序列号设为y。客户端收到后再发一个ACK报文确认号是y1连接建立。这时候双方都知道了对方的初始序列号后续数据传输时可以用序列号做可靠性的验证。这背后的门道在于TCP是面向字节流的协议数据被拆成一个一个段每个字节都有一个序列号。收发双方只有知道了对方的序列号起点才能正确排序和去重。如果没有握手过程直接发数据接收方无法判断哪个段先到哪个段后到也无法判断有没有丢段。面试题里常问“为什么不能两次握手”。从安全性角度说两次握手会导致一个明显问题重复的SYN请求会让服务端误建连接白白浪费资源而且服务端无法确认自己回复的SYN-ACK是否被客户端收到。有了第三次握手服务端只有在收到客户端ACK之后才会进入ESTABLISHED状态就能有效规避这种情况。实际排障时我见过服务器上大量SYN_RECV状态的连接这是半连接队列满了的表现常见原因是服务端处理不过来或者被恶意连接请求塞满。处理思路是调大somaxconn参数同时配合SYN cookies机制而不是简单重启服务。3.2 四次挥手和TIME_WAIT连接关闭里藏着的坑断开连接要四次挥手这比建立连接多了一次原因是TCP是全双工的两个方向的数据通道要各自独立关闭。客户端先发FIN表示“我不再发数据了”服务端回ACK表示“收到”但服务端可能还有数据要发所以不急着关闭等服务端把数据发完再发FIN客户端再回ACK。整个关闭过程是四次报文交互。其中TIME_WAIT是高频考点。主动关闭连接的一方在发出最后一个ACK之后不会立刻进入CLOSED状态而是要等2MSL最大报文生存时间的两倍。为什么等两个原因一是确保最后的ACK能到达对方如果丢了对方会重发FIN主动方通过TIME_WAIT还能处理二是让这条连接上的所有旧报文在网络中自然消失防止它和下一次使用相同四元组的连接混淆。这个机制在实际服务器排障中很常见。短连接服务如果频繁关闭连接你会发现服务器上TIME_WAIT连接特别多如果超出系统限制新连接就可能建不起来。生产环境我一般会结合业务场景调整这个参数对内部服务可以开启tcp_tw_reuse来复用TIME_WAIT连接但要确认前提是时间戳选项开启。而对外提供服务的场景我会优先考虑让应用层使用长连接而不是粗暴调整内核参数。3.3 可靠传输的四个关键机制TCP可靠性不只是靠三次握手那一下它是靠一套组合机制撑起来的。第一是序列号与确认应答每个数据段都有序列号接收方收到后回确认号表示“你发到这儿为止的数据我都收到了”。第二是超时重传发送方发出数据后启动定时器如果在规定时间内没收到ACK就重传这一段。第三是滑动窗口流量控制接收方通过窗口大小告诉发送方“你最多可以连续发多少数据不用等确认”发送方按这个窗口发就不会把接收方缓冲区塞爆。第四是拥塞控制它解决的是网络内部的拥堵问题和流量控制解决的“接收方能力”问题不一样。拥塞控制里有几个核心概念慢启动、拥塞避免、快重传、快恢复。慢启动是从一个很小的拥塞窗口开始指数增长直到到达阈值之后进入拥塞避免阶段窗口线性增长。一旦发生丢包说明网络可能拥塞了阈值会降到当前窗口的一半窗口回到初始值重来或者走快重传快恢复路径。这套机制解释了为什么新建立的连接前期吞吐量不高——窗口还不够大需要慢慢“探路”。实际开发里理解这些机制能避免很多误判。比如一条TCP连接在大带宽高延迟链路所谓的BDP场景上跑不满带宽原因往往不是带宽不够而是拥塞窗口还没增长到能填满管道的程度。这时候开启TCP窗口缩放选项或者用BBR这类更现代的拥塞控制算法效果会立竿见影。3.4 UDP不“简单”TCP也未必总适合你面试官经常追问“既然TCP这么可靠为什么还有UDP存在”。答案是很多场景根本不需要可靠传输或者自己可以在应用层做可靠性。UDP没有握手、没有确认、没有重传头部只有8字节比TCP头部小了将近一半也没有连接状态这意味着开销低、延迟低、转发性能高。视频通话、实时语音、游戏同步这些场景一个丢包的重传代价远高于直接丢掉一个旧帧。DNS查询也是典型的UDP应用一个请求一个响应丢了重发一次就行用TCP反而增加握手成本。后来UDP上还长出了不同方向的改进协议。传输方向有QUIC它在UDP之上自己实现了类似TCP的可靠性、加密和连接迁移能力专门解决HTTP/2时期TCP队头阻塞的问题。HTTP/3就是跑在QUIC上的。理解这条演进线索面试和实际选型都能用上不是所有可靠性都必须由TCP提供关键看业务对延迟和吞吐的需求。4. 应用层的两只看门狗HTTP与DNS4.1 HTTP请求过程与状态码速查应用层是离开发人员最近的协议层HTTP更是每天都要打交道。一个HTTP请求分成请求行、请求头、空行、请求体四部分。请求行里有方法、URL路径和协议版本比如GET /api/v1/user HTTP/1.1。请求头里最常用的有Host指定域名、User-Agent客户端标识、Content-Type请求体格式、Authorization认证信息。响应也一样有状态行、响应头和响应体。状态码按5个大类记2xx表示成功200是OK201是创建成功204是无内容3xx表示重定向301永久重定向302临时重定向304未修改命中缓存时会看到4xx表示客户端错误400参数错误401未认证403无权限404资源不存在429请求太频繁5xx表示服务端错误500服务器内部错误502网关收到无效响应503服务不可用504网关超时我实际排障中最常见的状态码是504和502。出现502通常是后端服务崩了或者连接超时出现504通常是网关和后端之间等待时间过长。这时候先看后端服务日志再看网关配置里面的超时时间基本能定位。而304出现次数多不代表服务器有问题它说明浏览器缓存正常工作我遇到过不少同事把304当异常其实不是。另外HTTP是无状态的协议为了维持登录状态引入了Cookie和Session机制。Cookie存在浏览器端每次请求自动带上Session存在服务器端通过Session ID关联。后续演进出了Token机制用JWT这类自包含的Token做认证让服务器不需要存会话信息在分布式环境下更好扩展。4.2 HTTPS加密链路TLS握手保证了什么HTTPS解决的问题本质上是HTTP的三桩罪明文传输、不验证通信方身份、数据容易被篡改。它的底层是TLS协议在TCP之上加了一层加密会话。TLS握手的核心逻辑是混合加密。第一步服务器把证书发给客户端证书里有服务器的公钥和CA机构的签名。第二步客户端验证证书有效性验证通过后用对方的公钥加密一个临时对称密钥发回去。第三步服务器用私钥解出这个对称密钥之后双方都用对称密钥加密通信数据。这样既解决了对称密钥分发难题通过非对称加密传输密钥又保证了后续通信的性能对称加密处理速度远快于非对称。搞懂这个流程很多面试问题就迎刃而解。比如“为什么要证书”因为公钥裸露在网络里你不知道它是不是真的来自你访问的网站CA的作用就是给公钥做背书。又比如“中间人攻击是怎么回事”就是黑客在客户端和服务器之间插入自己伪造证书骗取信任。客户端会报证书不可信这就是为什么公共WiFi下访问HTTP网站容易出问题而HTTPS的安全性从握手阶段就立起来了。在实际运维里验证TLS连接我常用openssl命令# 查看某个域名的证书信息和TLS握手详情 openssl s_client -connect example.com:443 -servername example.com这个命令能直接看到证书链、加密套件和握手结果排查证书过期、加密套件不支持之类的问题非常方便。4.3 DNS解析全流程与故障排查很多网络问题的根子其实卡在DNS上。一个域名解析的完整路径是浏览器先查本地浏览器缓存再查操作系统缓存hosts文件优先然后向本地DNS服务器发起递归查询本地DNS服务器再替你走迭代查询依次问根DNS服务器、顶级域名服务器、权威DNS服务器拿到最终的IP地址返回。关键参数是TTL它告诉缓存服务器这个解析结果能存多久。TTL设太长域名切换IP后生效慢TTL设太短解析请求量大。做域名迁移时标准做法是提前把TTL调小等切换完成后过一段时间再调回来这样能把缓存失效时间缩短到几分钟级别。我遇到过的DNS故障主要有几种表现一是域名解析到旧IP检查TTL和本地缓存二是解析不到任何IP先看本地DNS配置再看权威服务器是否正常三是部分地域解析异常通常是CDN调度问题需要查分线路解析配置。排查工具就三个nslookup查看解析结果dig查看详细的查询过程再到公共DNS服务器上对比解析。系统上还能用/etc/resolv.conf查看配置的DNS服务器地址——不过现在很多系统都用systemd-resolved管理了直接改这个文件不一定生效更稳妥的是用resolvectl或nmcli。5. 网络排查实战与避坑心得5.1 我屡试不爽的五步排查法网络问题最忌讳乱试。我习惯的排查流程是固定的沿着OSI分层从底往上走每层都有对应的命令第一步确认物理连接。看网卡状态ip link show如果状态是DOWN或者没有carrier基本就是网线、交换机端口的问题。第二步确认网络层配置。用ip addr看IP地址和掩码用ip route看默认路由先ping自己的网关IP通了再往外走。第三步确认到目标可达。用ping测延迟和丢包率用traceroute或mtr看路径上哪一跳异常。第四步确认端口和连接状态。用ss -tnp看本机监听端口和所有TCP连接状态用telnet ip port或nc -vz ip port快速验证远端某个端口是否开放。第五步看应用层请求。用curl -v看完整HTTP响应用浏览器开发者工具看请求耗时。这套流程走下来80%的问题都能定位到某一层。印象最深的一次是生产环境接口偶发超时从应用层一直查到链路层最后发现是物理机上某个网卡的多队列中断不均匀CPU单核跑满导致收包延迟。如果不是按分层排查很难把“接口超时”和“网卡中断”联系起来。5.2 高频故障速查表我先说几个最常见的故障和它们对应的方向现象可能原因优先排查命令/手段ping不通网关网卡未up、IP配置错、交换机端口隔离ip link、ip addr、arp -n能ping通IP但域名解析失败DNS服务器配置错误、DNS服务异常nslookup、dig、resolvectl status连接被拒绝端口未监听、防火墙拦截、服务未启动ss -tlnp、systemctl status、telnet请求超时中间设备丢包、防火墙静默丢弃、TCP握手过慢mtr、tcpdump抓握手包大量TIME_WAIT短连接过多、连接复用配置未开启ss -s统计、ss -tan服务偶发卡顿拥塞控制算法不合适、网卡丢包、CPU软中断高ethtool -S、top看si%HTTPS证书报错证书过期、证书链不完整、主机名不匹配openssl s_client、curl -v这张表不是万能答案它能帮你在紧急时刻快速圈定方向。真实环境下经常是多因素叠加比如某个供应商的专线抖动造成的丢包会被运维误判成服务端慢结果调了一晚上代码最后发现是运营商光衰过大。5.3 抓包定位问题的完整示例我给个真实的小案例。有一次某服务对外接口偶发延迟高持续了半个小时又恢复正常。先用ping测网关零丢包再测公网IP也没问题但一旦调用业务接口就慢。用tcpdump在客户端抓包命令是这样的tcpdump -i eth0 -nn tcp port 443 -w /tmp/trace.pcap然后立刻复现一次慢请求再抓包分析。一看包才发现TCP握手的第一个SYN发出去之后隔了整整1秒才收到SYN-ACK后续每个包都有接近1秒的间隙。这说明问题不在服务器处理逻辑而在TCP握手路径上。后来追到链路层发现是安全设备对某些TCP选项做了重组遇到特定窗口大小就延迟转发。如果当时直接去优化应用代码这个问题根本不可能解决。这就是抓包的价值——它让网络层面的问题不再靠猜。我强烈建议每个做后端和运维的同事至少掌握tcpdump的常用用法和Wireshark的基本过滤表达式。不会抓包之前网络问题像玄学会了抓包之后一切都有据可查。5.4 避坑心得关于内核参数和“调一下就好”排查过程中有一个容易走极端的点——动不动就调内核参数。网上很多文章说“把net.ipv4.tcp_tw_reuse设为1把tcp_max_tw_buckets调大”问题就解决了。我在生产环境上吃过亏这些参数是链路级的一个参数改动会影响整个节点所有连接而不只是你家那一个service。我的原则是能通过应用层解决的不动内核能通过架构解决的不动单机。短链接太多先考虑连接池连接池解决不了再考虑长连接真到了非调不可的程度先在测试环境做对比压测确认影响面后再上生产。另外调完内核参数要在重启后验证是否持久化用sysctl的配置要确保写进了/etc/sysctl.conf之类的持久化文件。还有个小技巧值得分享记着每个服务的正常延迟基线和连接数基线。没有基线你无法判断当前数据算不算异常。我会定期把一些核心指标的ss输出、ping延迟存下来哪怕只是存到本地日志里关键时刻对比一下比翻半天监控来得快。网络知识点这套东西看起来庞杂拆开之后其实就是一张分层地图加几个高频协议。每次遇到网络问题我都会在心里默念“从底往上逐层排除”——这个概念帮我在无数次抓狂的凌晨稳定了心态。也希望这篇梳理能让你在下次面对“连接超时”的时候心里不是一句“重启试试”而是一个清晰的排查路径。