先说个背景。前阵子有个朋友半夜给我打电话,说家里的摄像头突然连不上,Wi-Fi 信号满格但就是访问不了外网。我远程让他把光猫和路由器都重启了一遍,没用,最后让他把手机热点打开,摄像头连热点,好了,路由器这边的问题。他问了我一句:“那到底是路由器坏了,还是网络被黑了?”这个问题其实挺典型的,很多人对计算机网络的认知停留在“能上网就行”,一旦出问题就全靠重启,重启不行就换设备。但如果你懂一点底层原理,哪怕只是搞明白数据从一个设备到另一个设备经历了什么,大部分故障你都能在五分钟内定位到具体环节。
这篇内容我想把计算机网络的核心概念从头到尾捋一遍——从数据怎么从网线里变成比特流,到 IP 地址和路由怎么把人家的设备找到,到 TCP 怎么保证文件不出错,再到你输入一个网址后浏览器到底干了哪些事。我不会只讲理论,最后会把我实际排查问题用的那套方法论也放出来。适合刚入行的开发者、运维、网络管理员,以及那些想真正理解网络、不想再把“重启大法”当唯一手段的人。
1. 电脑之间到底怎么传数据:从一次共享文件失败说起
1.1 那次故障让我明白,网络问题必须分层面看
那台摄像头连不上外网,表面上是“路由器问题”,但“路由器”本身是一个很笼统的说法。它可能出在物理连接上,可能出在 IP 分配上,可能出在 DNS 解析上,也可能出在端口转发或者防火墙策略上。你如果不知道数据是怎么被一层一层打包、传输、再解包的,你就只能靠猜。
我后来给他换了一个方式排查。先让摄像头用 DHCP 拿到一个 IP,看它能不能 ping 通路由器的网关。能通,说明物理层和链路层没问题;不能通,那就是无线信号或者网线这块。再让他用手机同一个 Wi-Fi 看看能不能上网页,能上,说明路由器到运营商的链路没问题,那问题基本就锁定在摄像头这台设备的配置上。最后发现是摄像头固件里 DNS 服务器填了一个已经失效的地址,改成自动获取就恢复了。
你能看到,这套排查思路的本质,就是沿着网络分层模型从上往下或者从下往上一层层确认。所以理解分层模型不是背概念,是真的能救命。
1.2 为什么一定要“分层”,而不是一个协议干所有事
网络协议如果只做成一个巨大的算法,让所有设备都遵循同一套规则,理论上也能通信。但实际网络里有几亿台设备,有无数厂商,总不能要求每台设备都把整个通信逻辑全部实现一遍。分层的好处是:每一层只解决一个特定问题,层与层之间通过标准接口通信,上层不用关心下层的实现细节。
最常用的模型是 OSI 七层模型和 TCP/IP 四层模型。七层听起来复杂,但记住一句话就行:数据越往下越接近物理信号,越往上越接近人能理解的语言。应用层是 HTTP、DNS 这些,传输层是 TCP/UDP,网络层是 IP,链路层是 MAC 地址和以太网帧,物理层就是网线和电压信号。
实际工程里,TCP/IP 四层模型更常用:应用层、传输层、网络层、网络接口层。你写的程序基本只碰应用层,操作系统帮你处理传输层和网络层,网卡驱动处理网络接口层。这也是为什么很多开发同事聊网络喜欢说“四层”而不是“七层”。
1.3 数据封装:你发一条消息,它经历了什么
假设你在浏览器里输入一个网址。你的数据从应用层产生,在传输层被切成一个个 TCP 段,每个段加上源端口和目标端口;在网络层加上源 IP 和目标 IP;在链路层再加上源 MAC 和目标 MAC,最后变成比特流通过网线发出去。
这个过程叫封装。每一层加上去的头,就像寄快递时套上去的快递单。收件那一侧则是一层一层剥掉这些头,叫解封装。
有个细节很多人忽略:一个 TCP 段能不能发给下一个设备,不是由目标 IP 决定的,而是由路由表决定的。在你自己的电脑上,下一跳往往是网关;在没有到达目标网络前,每一跳的路由器都在做同样的决策。所以数据在网络上不是“直接跳到目标”,而是一站一站接力过去。这就是“跳数”和“延迟”的来源。
2. IP地址、子网掩码和路由:定位与寻路的三板斧
2.1 IP地址不是一串数字,而是一张“门牌系统”
IPv4 地址有 32 位,通常写成四个十进制数字,比如 192.168.1.100。它分为网络部分和主机部分。网络部分决定了你这台设备属于哪个“区域”,主机部分决定了你在该区域里的编号。路由器转发数据时只看网络部分,到了目标网络之后才看主机部分。
这个设计非常关键。如果每个路由器都要记住全球每一台主机的地址,那路由表会爆炸。它只需要记“哪个网段从哪个方向走”就够了,剩下的最后一步交给目标网络内部的设备。
所以当你配置静态 IP 时,最重要的三个参数是:IP 地址、子网掩码、默认网关。IP 地址是门牌号,子网掩码告诉系统哪些门牌属于同一片区,默认网关是片区出入口。很多人配置网络只改 IP,不改掩码和网关,结果网关不在同一片区内,数据发不出去。
2.2 子网掩码背后的计算逻辑,其实用二进制看最直观
子网掩码的作用是划分网络位和主机位。拿 255.255.255.0 来说,它的二进制是连续 24 个 1 再加 8 个 0。如果你和另一台设备的 IP 分别和这个掩码做按位与运算,结果相同,说明你们在同一个子网里,直接通过交换机就能通信,不需要路由器。
举个例子:
- 192.168.1.10 与 255.255.255.0 按位与,得到 192.168.1.0
- 192.168.1.200 与 255.255.255.0 按位与,得到 192.168.1.0
- 这两个地址在同一个子网,可以直接通信。
如果你把掩码改成 255.255.255.128,那么主机位只剩 7 位,这个子网的地址范围实际是 192.168.1.0 到 192.168.1.127,另一块是 192.168.1.128 到 192.168.1.255。192.168.1.200 就和 192.168.1.10 不在一个子网了,它们之间必须靠路由器转发。
CIDR 表示法就是把掩码写成斜杠加前缀长度的形式,比如 /24 就是 255.255.255.0。网络工程里规划 IP 的时候,最常用的就是 /24、/23、/30 这些。像我之前给某中型办公室划网段,办公区用 /24 分几个 VLAN,设备间互联用 /30 只留两个可用 IP,这样既省地址又方便路由收敛。
2.3 路由表怎么决定数据往哪走
路由器是一个专门干“转发”的设备,它的核心数据结构叫路由表。路由表里至少有几类条目:直连路由、静态路由、动态路由协议学到的路由。
查询规则是“最长前缀匹配”:如果目标 IP 同时匹配两条路由,前缀更长的那条优先。什么意思呢?比如一条路由是 0.0.0.0/0(默认路由,匹配所有人),另一条是 192.168.0.0/16(匹配 192.168 开头的地址),数据发往 192.168.5.10 时会走后者,因为它的前缀更长,更精确。
这就像你在快递分拣中心查一份地址,如果只知道“发往浙江”和“发往杭州余杭区”,那显然杭州余杭区这条线路更精确,哪怕两条线路最终都会汇聚到同一个地方。
还有一个容易误解的点:路由器和交换机的区别。交换机工作在二层,根据 MAC 地址转发,它不知道什么是 IP;路由器工作在三层,根据 IP 地址转发。家用路由器其实是个三合一设备:路由、交换机、无线接入点都集成在了一个小盒子里。所以家里网络出问题,得很小心地判断到底是哪一部分出了问题。
3. TCP和UDP:为什么视频能实时看、文件却不能出错
3.1 三次握手到底在确认什么
TCP 是面向连接的协议。所谓“连接”不是物理上拉了一条线,而是在两个设备之间建立一套状态同步机制。三次握手发生在数据传输之前,目的是确认双方的发送能力和接收能力都正常。
过程是:客户端发送一个 SYN,表示“我要建立连接”,同时带上一个初始序列号;服务端收到后回复 SYN+ACK,表示“我收到了你的请求,我的接收能力没问题,现在请你确认我的发送能力”;客户端再回一个 ACK,表示“我也确认了你的发送和接收能力”。到这一步,双方都确认了自己能发、能收、对方也能发、能收,连接建立。
为什么要三次而不是两次?因为 TCP 的网络是不可靠的,可能出现延迟和重复。如果只有两次握手,服务端无法确认客户端是否真的收到了自己的回应;极端情况下,客户端发了一个 SYN 但迟迟没收到回复,于是重发了一个,而第一个 SYN 的网络延迟导致旧的连接请求先到达,就会造成资源浪费。三次握手能把这种历史重复报文的影响降到最低。
实际抓包时候你经常能看到一个现象:客户端连续发 SYN,服务端就是不回。别急着换网线,先看看是不是服务端的连接队列满了。这队列在 Linux 里叫 SYN Backlog,如果某个应用处理不过来,握手就会卡住,大约一半的“连不上”问题都出在这里。
3.2 四次挥手和 TIME_WAIT 这个隐藏坑
断开连接时,TCP 用了四次挥手,而且一定会有一个被动关闭方进入 TIME_WAIT 状态,等待两个 MSL(报文最大生存时间)才彻底关闭。
为什么需要等待?因为最后一个 ACK 报文可能丢失,如果服务端没收到,会重发 FIN;客户端如果立刻把连接关掉,就收不到重发的 FIN 了。所以在 TIME_WAIT 期间,客户端还能处理服务端重发的报文。
这个状态在高并发场景里是很经典的问题来源。一个服务端程序大量处理短连接,你会发现系统里 TIME_WAIT 状态的连接数量非常多。不严重的话危害不大,但如果达到几万个,可能会占用大量内存和端口。经验做法是:如果是服务端主动关闭连接导致 TIME_WAIT 堆积,优先排查代码里的 keep-alive 设置;如果是客户端需要发起大量连接,可以调整端口范围或开启 tcp_tw_reuse。但我不建议无脑开启 tcp_tw_reuse,它对连接双方的行为有额外要求,用不好反而会出现连接串号这种更难查的问题。
3.3 TCP拥塞控制:丢包时TCP在做什么
很多人以为 TCP 丢包就是坏事,其实 TCP 最核心的能力就是处理丢包。它通过序列号和确认号来识别哪些数据被收到了,哪些需要重传。但单纯的重传还不够,因为如果网络已经堵塞,你越是重传就越堵。所以 TCP 引入了拥塞控制。
拥塞控制大概分几个阶段:慢启动、拥塞避免、快速重传、快速恢复。慢启动阶段,发送窗口指数增长,直到逼近一个阈值;之后进入拥塞避免,线性增加;一旦发生丢包,就把窗口减小,然后再逐步探回去。
这个机制直接决定了你在实际业务里看到的吞吐量为什么不是“带宽多大就传多快”。如果你在一个丢包率比较高的网络里传大文件,哪怕带宽有 100M,实际速度也可能只有 1M,因为 TCP 一直在降窗和重传。UDP 就不一样,它不管丢不丢,发了就完事,所以视频通话、直播这类对实时性要求高、对少量丢包不敏感的场景,全都跑在 UDP 或者基于 UDP 的 QUIC 上。
有个小细节值得记一下:当你在业务里做性能调优,发现“TCP 传大文件速度上不去”,先别急着怀疑程序代码,用工具看一下重传率和 RTT。如果重传率高,调大缓冲区反而可能更糟,正确做法是压低并发、减少突发的流量。
4. DNS和HTTP:打开网页时真正发生的事
4.1 DNS 这层你平时根本看不见,但它一坏全网瘫痪
你在浏览器输入一个域名,第一步不是发包给目标服务器,而是先问 DNS:“这个域名对应的 IP 是多少?” DNS 本质是一个分布式的电话簿系统,它把人类可读的域名翻译成机器可读的 IP 地址。
完整的解析链路通常是这样:先查浏览器缓存,再查操作系统缓存,然后再查你配置的本地 DNS 服务器(通常是运营商或者公共 DNS)。本地 DNS 如果没有缓存,它会帮你向根域名服务器问顶级域服务器,再向权威域名服务器问具体记录,拿到结果后缓存起来再返回给终端。
有一个常见谬误,就是“DNS 解析失败等于上不了网”。其实 DNS 只是解析域名,你直接用 IP 地址访问网站是绕开 DNS 的。但绝大多数应用都依赖域名,所以 DNS 挂了,用户感知就是“断网”。
排查 DNS 问题时,最简单的命令是 nslookup 或者 dig。我见过太多人一遇到上不了网就先换路由器,结果换了还不行,最后一查是某台设备把 DNS 指到了内网一个已经停掉的地址上。先看 DNS 再动硬件,能少花很多冤枉钱。
4.2 HTTP 从 1.0 到 HTTP/3 的演进,核心是性能
HTTP/1.0 时代,每个请求都要建立一个新的 TCP 连接,开销很大。HTTP/1.1 引入了持久连接,但一个新的问题是队头阻塞:如果第一个响应慢了,后面的响应就得排队,即使它们在完全不同的资源上。
HTTP/2 通过在一个连接里多路复用多个流,解决了应用层的队头阻塞,但它仍然跑在 TCP 上。而 TCP 本身还有队头阻塞:如果一个 TCP 数据包丢了,即使后面的包已经到了,TCP 也要等重传才能把数据交给上层,HTTP/2 在这种情况下的表现反而可能比 HTTP/1.1 还被诟病。
HTTP/3 直接把传输层换成了基于 UDP 的 QUIC,在用户态实现了可靠传输和加密,避开了 TCP 的流内队头阻塞。所以如果你现在要新做一个高实时性的 Web 应用,HTTP/3 是非常值得考虑的方向。不过实际部署时要注意,HTTP/3 使用 UDP 传输,很多中间设备的防火墙默认会对 UDP 流量限速,有时候你明明开了 HTTP/3,用户却一直落在 HTTP/2 上,就是中间网络设备在捣乱。
4.3 HTTPS 的握手过程,和证书信任链
HTTPS 不是 HTTP 加上简单加密,它是在 HTTP 和 TCP 之间加了 TLS 层。TLS 握手的第一件事是协商加密算法和交换密钥。现代的 TLS 1.3 把往返次数从两次缩短到一次,所以握手更快。
握手完成后,浏览器会验证服务器的证书。验证证书本质是验证“这个证书是不是可信的 CA 签发的”,浏览器里预置了根证书信任列表,通过证书链一级一级往上追溯。如果证书过期、域名不匹配、或者签发机构不被信任,浏览器就会报警。
这里有个经验:别通过“把证书校验关掉”来解决证书报错,这会在某个时间点爆炸。正确做法是看证书链里中间证书有没有正确部署。经常会出现服务端只发了叶子证书、没发中间证书的情况,某些客户端能补全,某些不能,表现就是“手机上能打开、电脑上报错”,或者反过来。
5. 实战排查:从现象到根因的四步方法
5.1 第一步:先分清是哪个层面的问题
排查网络问题时,我最忌讳一上来就抓包。先问自己:“问题的现象是什么?发生在哪个范围?”
一台设备有问题,还是所有设备都有问题?如果是所有设备都有问题,说明问题在集中出口,比如路由器、光猫或者外部链路。如果只是某台设备有问题,就要先查这台设备的 IP、网关、DNS 配置,再查硬件连接。这个“分隔”的思路,就是把刚刚学的分层模型直接落地。
5.2 第二步:用 ping 和路由跟踪缩小范围
ping 这个命令用的是 ICMP 协议,它能在没有上层应用依赖的情况下测试两台设备之间能否互相到达。先 ping 自己的回环地址 127.0.0.1,确认网卡和协议栈正常;再 ping 网关,确认二层三层链路正常;再 ping 外网 IP,确认路由和运营商链路正常;最后解析域名看 DNS 是否正常。
如果需要更细的路径分析,用 traceroute(Linux/Unix 下是 traceroute,Windows 下是 tracert)。它会显示从你的设备到目标之间经过了哪些跳。每一跳的时延能大概看出哪一段链路慢。
有一个细节,ping 不通不代表网络不通。某些服务器主动禁了 ICMP,不回应 ping,但 HTTP 服务是正常的。所以 ping 不通时不要急着下结论,还要结合具体端口做测试。
5.3 第三步:抓包确认关键节点的行为
当确认问题在某一个节点上,但不知道它为什么异常时,抓包就是最直接的手段。常用开源抓包工具首推 Wireshark。它能把每一个数据包的帧内容都展示出来,包括源 MAC、目标 MAC、源 IP、端口、TCP 标志位等等。
我举个例子。某次排查办公网络“网速慢”,ping 完全正常,下载速度却比带宽低很多。抓包以后发现大量 TCP 重复确认和快速重传,说明中间链路存在丢包。顺着链路用路由跟踪,发现某个跳的时延突然飙升到几百毫秒。再联系机房那边,确认是那台交换机光模块异常,换掉之后速度马上恢复正常。
如果没有抓包,单凭“网速慢”这个现象,你可能排查一天都找不到方向。抓包不是高级玩家才能用的技术,它只是把“看不见的交互过程变成看得见的日志”。
5.4 第四步:修完以后还要做的验证
修复问题的最后一个步骤往往被忽略。你改了一个配置之后,不能只看“好像恢复了”,还要确认根因确实被消除。比如你换了 DNS 地址,那就要反复解析几次确认稳定;你调整了路由器的 MTU,那就要实测长时间大流量传输,看丢包率是不是归零。
验证阶段有一个好习惯:把每一步操作、每一个现象都记录下来。很多人修网络问题靠“记忆里的某个操作”,改完以后自己也忘了改了啥,下次再出问题就只能从头再来。记下来以后,问题复现时可以快速回滚。这个习惯帮我省了非常多的重复排查时间。
6. 不得不说的几个常见误区
6.1 误区一:IP 地址冲突和网关配置混淆
IP 地址冲突的原因是同一子网里两台设备用了同一个 IP。表现是设备时好时坏,重启后可能好一阵又坏。检测方法是查看设备日志里的地址冲突提示,或者在网关上查看 ARP 表,找到同一个 IP 对应多个 MAC 地址的情况。
网关配置错误的表现更隐蔽。IP 地址和掩码都正常,就是出不了网。这时你 ping 网关,如果网关能通,但外网不通,先查是否有静态路由指向了错误方向;如果网关都 ping 不通,那就要看设备和网关的 IP 是否真的在同一子网内。
6.2 误区二:带宽和延迟分不清
带宽是水管粗细,延迟是水流速度。很多人说“网卡”,其实说的是高延迟或高丢包,而不是带宽不足。下载快慢由带宽和并发决定,网页打不开更可能是延迟和请求阻塞导致。
你测速时如果发现“下载 100M,打开网页却转圈”,别急着投诉运营商。先访问几个不同网站做对比,如果全部转圈,检查 DNS 和路由器连接数;如果只有某个网站慢,那问题可能在目标服务器或者链路。
6.3 最后说点个人体会
学网络,千万不要试图背熟每一个协议的全部字段。真正有用的能力是:当你看到一个“连不上”的现象时,能快速想起这个现象最可能对应哪一层,然后逐层排除。计算机网络的核心概念说多不多,说少不少,把分层模型、IP 寻址、TCP 状态机制、DNS 解析这四件事彻底搞明白,工作和家里的绝大多数网络问题,你都能做到心里有数。
如果你刚入门,我给你的建议很简单:找一台自己的电脑,把 IP 改成静态配置一次,故意把网关填错,再故意把 DNS 填错,然后用刚才说的那套排查流程走一遍。这种“故意搞坏”的实验,比你看十遍教科书都管用。等你自己亲手排掉一次真实的网络故障,那些协议的名字才算真正刻进脑子里。