ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

计算机网络入门:从DNS解析、三次握手到HTTP缓存

计算机网络入门:从DNS解析、三次握手到HTTP缓存

简介:《计算机基础.pdf》是代码随想录知识星球「最强八股文」第五版的计算机基础分册,面向准备后端、前端及全栈岗位技术面试的开发者,聚焦计算机网络这一高频考点。内容围绕三次握手与四次挥手、HTTP 与 HTTPS 的区别、HTTP 强缓存与协商缓存、DNS 域名系统展开,并以「浏览器输入 URL 后发生了什么」为主线,串起 URL 解析、DNS 查询、TCP 建连、请求响应到页面渲染的完整链路;DNS 章节还延伸到集中式设计的单点故障与远程延迟问题、域名层级结构、递归查询与迭代查询的差异,便于按面试问答的粒度记忆。资源为单个 pdf 文件,压缩包约 37.83MB,已整理成体系化文档,可直接打印或按章节精读。目前已有 778 人学习,适合需要系统梳理网络基础、补齐面试答题要点、从零散博客转向结构化复习的初中级开发者。

1. 先搞懂一件事:计算机基础这门课,到底在教你什么

很多人第一次认真看「计算机基础」这四个字,是在招聘要求上:十条里有八条写着「熟悉计算机网络」。心里一紧,翻开教材,满眼都是缩写和协议名,越看越发怵,觉得自己是不是漏学了什么。

其实这门课没那么玄。它讲的事情很朴素:两台电脑之间,怎么把一句话准确送到,又怎么确认对方真的收到了。你点开一个网页、发一条消息、扫一次码付款,底下跑的都是这套流程。

《计算机基础.pdf》这一篇,就是从「在浏览器里输入一个网址,按下回车之后发生了什么」这道题起步,把网络这条线上的关键节点一个个讲开:域名怎么变成地址、连接怎么建立、数据怎么传、连接又怎么断开。它不要求你先会写代码,适合完全没接触过、又想在面试和日常排查里少翻车的新手,先当成一张地图看一遍。

2. 从敲下回车那一刻拆起:一次网页访问的七个步骤

这是整个计算机网络里出现频率最高的一道题,也是新手最值得先啃下来的一块。原因很简单:它不是孤零零一个知识点,而是一根绳,把 URL、DNS、TCP、HTTP、缓存、渲染全串在了一条线上。你把这条线捋顺了,后面学什么都像往钩子上挂东西,有地方挂。

我习惯用打电话来类比。你要找一个人办事:先得知道他的号码(DNS),拨过去等对方接(建立连接),接通了说事(发请求)、对方回你(响应),事情说完要挂电话(断开连接)。网页访问一模一样,只是把「说话」换成了数据包。

七个步骤分别是:解析 URL、DNS 域名解析、TCP 三次握手、发送 HTTP 请求、服务器处理并返回响应、浏览器渲染页面、TCP 四次挥手。下面三小节按顺序走一遍。

2.1 前三步:URL 拆包、DNS 找地址、三次握手

第一步,浏览器拿到你输入的网址,先拆件。它会把协议(http 还是 https)、主机名、端口、路径分别抠出来,然后拼成一个 HTTP 请求。在真正发出去之前,浏览器还会翻一下自己的缓存:这个资源我是不是刚拿过、还没过期?如果有,直接就用,连网络都不用走。这一步看着不起眼,但后面 HTTP 缓存那一大块内容全是从这儿分叉出去的。

第二步是 DNS 解析。人能记住www.example.com,机器只认192.0.2.1这样一串数字。DNS 干的就是翻译的活。翻译不是一次到位的,中间要问好几个人:

  1. 先看浏览器自己的缓存里有没有;
  2. 没有就问操作系统的 hosts 文件;
  3. 还没有,就去找本地 DNS 服务器(通常是网络服务提供商给的那个);
  4. 本地 DNS 服务器没缓存,就去问根服务器「.com该找谁」;
  5. 根服务器不负责具体域名,只告诉你去问哪个顶级域服务器;
  6. 顶级域服务器同样只指路,告诉你去找哪个权威服务器;
  7. 权威服务器才是真正存着「这个域名对应哪个 IP」的地方,把结果给回来;
  8. 本地 DNS 拿到结果,返回给浏览器,顺手缓存一份。

这里有个新手很容易混的点:递归查询和迭代查询。用大白话说,递归就是「我托你办,你帮我跑完全程,最后把结果给我」;迭代就是「我问你一句,你只告诉我下一站去哪儿,我自己接着跑」。客户端对本地 DNS 服务器用的是递归,本地 DNS 服务器对根、顶级、权威服务器用的是迭代。把这个「谁替谁跑腿」分清楚,这两个词就不会再打架。

第三步,拿到 IP 了,该建立连接了。TCP 的三次握手,表格列出来更清楚:

次数谁发起发了什么这一步确认了什么
第一次客户端SYN,带上自己的初始序号服务器知道:客户端能发
第二次服务器SYN + ACK,带上自己的初始序号并确认对方的客户端知道:服务器能收也能发
第三次客户端ACK,确认服务器的序号服务器知道:客户端能收

面试官最爱追问的是「为什么是三次,不是两次也不是四次」。两次的问题在于:服务器发完自己的 SYN+ACK 之后,并不知道客户端到底收没收到。如果这次回应在半路丢了,服务器已经单方面认为连接建立好了,白白占着资源等一个永远不会来的数据。三次刚好让双方都完成「我发的你能收、你发的我也能收」的互相确认。至于四次,纯属多余,第三次已经把话说完了。

还有一个常问的:第一次握手丢了会怎样?答案不复杂——客户端等不到回应,会按超时时间重发 SYN,重发几次还不行就报连接超时。服务器那边因为根本没收到,不会分配任何资源,所以不会有什么损失。这也正是三次握手而不是两次的实际价值所在。

2.2 第四、五、六步:请求发出去、服务器回话、页面画出来

连接建好,第四步就是把 HTTP 请求发出去。一个请求报文的结构是「请求行 + 请求头 + 空行 + 请求体」。请求行里写着方法(GET、POST 这些)和路径;请求头是一堆键值对,告诉服务器我想要什么格式、我带了什么 Cookie、我支持什么压缩方式。

这一步能岔出去的问题特别多:HTTP 和 HTTPS 差在哪儿(HTTPS 在 HTTP 和 TCP 之间加了一层 SSL/TLS,把明文变成密文)、GET 和 POST 有什么区别、常见的状态码都是什么意思。状态码按开头数字分组记最省事:2 开头是成功,3 开头是重定向,4 开头是客户端的问题(比如 404 找不到、403 没权限),5 开头是服务器自己出了状况。

第五步,服务器收到请求,交给对应的处理程序,处理完拼一个响应报文回来。响应报文里除了网页内容本身,还有几个头部字段值得留意:Content-Type说明返回的是什么类型,Content-Encoding说明用了什么压缩方式,Cache-Control和ETag决定这个资源能被缓存多久、下次怎么验证,Set-Cookie则是服务器往你浏览器里塞的身份凭证。

第六步,浏览器拿到内容开始画页面。大致的流程是:解析 HTML 生成 DOM 树,解析 CSS 生成 CSSOM 树,两棵树合起来算布局,最后绘制到屏幕上。这里有个前端同学必会的区分:布局位置变了叫回流(重排),只改颜色背景叫重绘。回流的代价比重绘大得多,所以写样式时尽量别频繁改动宽高和位置。

顺带说一句 HTTP 的「无状态」。服务器天生不记得你是谁,上一次请求和这一次请求在它眼里毫无关系。这事儿有好处——不用为每个用户存一堆状态,服务器轻松;坏处是登录这类连续操作没法做。解决办法就是 Cookie:服务器在响应里写一个标识,浏览器之后每次请求都自动带上,服务器一看就认出来了。

2.3 第七步:四次挥手,以及为什么不能少一次

事情办完要挂电话。TCP 断开连接用的是四次挥手:

  1. 客户端发 FIN:我这边没数据要发了;
  2. 服务器回 ACK:知道了,你先等着;
  3. 服务器发 FIN:我这边也发完了;
  4. 客户端回 ACK:好,那我关了。

为什么是四次不是三次?因为 TCP 是全双工的,两个方向的数据通道要分别关。服务器收到客户端的 FIN 时,可能手里还有数据没发完,所以不能把「我收到了」和「我也发完了」合并成一条消息发回去,只能先 ACK,等自己真的发完了再单独发 FIN。这就是比握手多一次的根本原因。

主动关闭的那一方在发完最后一个 ACK 之后,还会进入一个叫 TIME_WAIT 的状态,等上一小段时间才真正关闭。入门阶段不用深挖它到底等多久、为什么是那个数,知道有这回事、知道它是为了确保最后那个 ACK 能到达对方就行了,等以后排查端口占用问题时自然会回头找它。

3. 为什么新手要优先啃网络这块:三个绕不开的理由

知道了流程长什么样,下一个问题自然是:为什么偏偏是这块,而不是操作系统、数据库、算法?这些当然也重要,但对零基础的人来说,起步顺序很关键。先把网络拿下,理由有三个,一个比一个实际。

3.1 它是面试里出现频率最高的一道筛子

不管投后端还是前端,网络题几乎躲不掉。三次握手、四次挥手、HTTPS、HTTP 缓存、TCP 和 UDP 的区别,这几样属于「不问才奇怪」的级别。面试官盯着这些问,不是想听你背定义,而是想看你能不能把一件事从头到尾讲明白。

这道「输入网址到页面显示」的题之所以金贵,在于它是一道可以自己控制走向的题。你答得好,可以主动把话头引到自己熟的地方:想聊缓存就说「这里浏览器会先查缓存」,想聊 HTTPS 就说「这里建立的是 TLS 连接」,想聊渲染就说「这里会牵扯回流重绘」。面试节奏就握在你手里了。反过来,如果这条主线是断的,被追问两句就只能是支支吾吾地蹦词儿。

而且这类问题有个特点:答案短,追问长。你答「三次握手是为了防止失效的连接请求」,面试官下一句就是「那第一次握手丢了会怎样」。只背结论的人,第二层就掉下去了。

3.2 出问题的时候,它是最省时间的那张排查地图

抛开面试不谈,网络知识在日常工作里的回报也很直接。一个页面打不开,原因可能有十几种,瞎试是最费时间的。但如果你脑子里有那张流程图,排查就是顺着链条走:

  • 域名解析对不对?查一下 DNS 记录就知道;
  • 解析对了但连不上?看看端口通不通、防火墙拦没拦;
  • 连上了但返回的东西不对?看状态码和响应头;
  • 内容对但每次都是旧的?八成是缓存没清干净。

这套顺序的价值在于「排除法」。每走一步就砍掉一批可能性,而不是东一榔头西一棒子。我带过的新人里,进步最快的那个不是代码写得最多的,而是遇到问题会先说「我先确认一下是解析问题还是连接问题」的那个。

3.3 零基础最怕碎片,得先立一根主干

零基础学计算机最容易掉进的坑,是把知识点当成一堆互不相干的卡片去背。背了三次握手,又去背 HTTP 版本,再去看 DNS,每一块都似懂非懂,合起来还是一团浆糊。

网络这块的好处是它天然有一条主干:一次访问流程。所有知识点都能挂在这条主干的某个位置上。DNS 挂在第二步,握手挂在第三步,缓存挂在第一步和第六步之间,HTTP 版本演进挂在第四步和第五步。挂上去之后,你脑子里存的不是十张卡片,而是一棵树。以后学新东西,也知道往哪个枝丫上接。

这也是这份《计算机基础.pdf》编排上的一个用心之处:它没有一上来就罗列协议定义,而是先用那道超高频题把整条链路走一遍,再往每个节点上填细节。对新手来说,这种「先看地图再走路」的顺序,比「先背概念再拼图」友好太多。

4. 第一个动手练习:用开发者工具和一条命令,把请求拆开看

光看流程图,永远隔着一层。真正的理解发生在你亲眼看到一条请求从发出去到回来的那一刻。好消息是,这件事不需要装任何环境,浏览器里就自带工具。整个练习大概十分钟,跟着做一遍,前面讲的那些名词会立刻变得具体。

4.1 打开 Network 面板,先认四列就够

随便打开一个网页,按下 F12,找到 Network(网络)面板,然后刷新页面。你会看到一长串请求刷出来,第一眼确实有点吓人。别慌,先只看四列:

  • Name:请求的资源名字,通常是一个文件;
  • Status:状态码,200 是成功,304 是用了缓存,404 是找不到;
  • Type:资源类型,document 是网页本身,script 是脚本,stylesheet 是样式;
  • Time:这一条花了多久。

点第一条(一般是那个 document),右边会弹出一个详情面板。里面有 Headers、Preview、Response、Timing 几个标签。先看 Headers,你会发现它分成三块:General(请求地址、方法、状态码)、Response Headers(服务器回的)、Request Headers(你发出去的)。前面讲的「请求头和响应头」在这儿变成了一屏能看到的东西。

提示:勾上「Disable cache」再刷新,你会发现请求变多了、时间变长了。这就是缓存的作用,直观得有点残忍。

再切到 Timing 标签,你能看到这条请求的时间被拆成了好几段:排队、DNS 查询、建立连接、等响应、下载内容。如果某一段特别长,问题基本就在那儿。这是新手排查慢请求最快的一招。

4.2 亲手发一次请求:一条命令和十行代码

浏览器把很多东西藏起来了,想看得更裸一点,用命令行。下面这条命令只取响应头,不下载网页正文:

# -I 表示只要响应头;-s 表示静默模式,不打印进度条 curl -I -s https://www.example.com

跑完你会看到类似这样的输出:状态行、Content-Type、Cache-Control、ETag、Last-Modified。这几个字段就是后面缓存那一节的实物。参数说明:-I是「只要头部」,-s是「安静点」,实际用的时候把网址换成你要查的那个站点就行。

想看得更细,加上-v:

# -v 打印全过程:DNS 解析、TCP 连接、TLS 握手、请求头、响应头 # -o /dev/null 把正文丢掉,只看过程 curl -v https://www.example.com -o /dev/null

输出里带*的那些行,就是连接的建立过程:先解析出 IP,再连上去,如果是 https 还要多一步握手,然后才把请求头发出去。前面讲的三次握手你在这看不到原始报文(那是传输层的事,被系统藏起来了),但「连接建立」这一步是实打实能看见的。

再往下走一层,用 Python 自己发一次,把状态码和响应头打出来:

import urllib.request url = "https://www.example.com" req = urllib.request.Request(url, method="GET") # 默认的 User-Agent 是 Python-urllib,有些站点会直接拒绝,这里换成常见浏览器标识 req.add_header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)") with urllib.request.urlopen(req, timeout=10) as resp: print("状态码:", resp.status) # 200 表示成功 for key, value in resp.headers.items(): print(f"{key}: {value}") # 逐条打印响应头

这段代码干的事和浏览器一模一样:构造请求、加上请求头、发出去、拿回响应。timeout=10是超时时间,超过十秒还没回应就抛异常,避免程序卡死。resp.status是状态码,resp.headers是一个大小写不敏感的字典,取Content-Type时不用管大小写。跑通它,你就从「看别人发请求」变成了「自己发请求」。

顺便把 DNS 也验证一下:

# 查询域名的 A 记录,+short 只输出结果 IP dig www.example.com A +short # Windows 上通常没有 dig,换成:nslookup www.example.com

如果这里查出来的 IP 和浏览器访问的对不上,或者干脆查不到,那问题就出在解析环节,后面的都不用看了。

4.3 从响应头里读出缓存策略:强缓存和协商缓存

前面反复提到缓存,现在可以拿真实数据看一看了。HTTP 缓存分两类,判断依据全在响应头里。

第一类叫强缓存。服务器返回Cache-Control: max-age=3600,意思就是「这个资源一小时内别来问我了,直接用你手里的」。在这一小时内,浏览器连请求都不会发,状态码那一列可能显示(from disk cache)或者干脆没有网络记录。这是最快的一档,也是新手最容易翻车的一档——你改了服务器上的文件,刷新页面却还是旧的,八成就是它。

第二类叫协商缓存。强缓存过期之后,浏览器不会直接重新下载,而是先去问一句「我手里这份还能用吗」。它带的凭证有两种:If-None-Match对上服务器给的ETag,或者If-Modified-Since对上服务器给的Last-Modified。服务器一看没变,回一个 304,意思是「没改,你继续用」。304 的响应体是空的,省下的是流量和时间。

验证方法很直接:在 Network 面板里勾掉 Disable cache,正常刷新一次,记下某条请求的ETag;再刷新一次,看状态码是不是变成了 304。如果是,说明协商缓存生效了。想强行绕过缓存,用 curl 加一句:

# 带上 no-cache,强制走一次协商,看服务器是不是回 304 curl -I -s -H "Cache-Control: no-cache" https://www.example.com

-H是自定义请求头,这里塞了一个Cache-Control: no-cache。注意它不是说「不要缓存」,而是说「用之前必须先跟服务器确认一下」,语义上属于协商缓存那一档,这个区别新手特别容易搞错。

5. 新手避坑:五个最容易翻车的理解误区

学这块内容,最怕的不是看不懂,而是「以为自己看懂了」。下面五条是我见过的翻车率最高的,每条都按「现象 → 原因 → 解决」写,对号入座看看有没有中招。

5.1 概念上的三个坑:把「背过」当成「懂了」

坑一:回答三次握手只会背那一句话。

现象:被问「为什么是三次不是两次」,张口就是「为了防止已失效的连接请求报文段突然又传到服务端」,面试官再问一句「那具体是怎么防的」,就答不上来了。

原因:这句话是从别处抄来的结论,中间的推理过程你并没有走过。结论可以背,推理不行。

解决:别背句子,画时序图。拿张纸,把客户端和服务器画成两条竖线,把三次报文各带什么、每一步之后双方分别确认了什么,一格一格写出来。写完你会发现,「为什么不是两次」根本不用背,因为它自己就浮出来了。

坑二:以为 HTTP/1.1 的管道化是默认开启的。

现象:讲 HTTP/1.1 优化的时候,信誓旦旦说「管道化让请求可以连着发,性能提升明显」。

原因:看到「管道」两个字,想当然地认为浏览器都在用。

解决:记住两个事实——它不是默认开启的,而且主流浏览器基本都没支持。真正让 HTTP/1.1 难受的是队头阻塞:服务器必须按请求顺序回,前一个卡住了,后面全得排队。管道化只解决了「请求能不能连着发」,没解决「响应能不能乱序回」,所以它没能救场。

坑三:以为 HTTP/2 把队头阻塞彻底解决了。

现象:很流利地说出「HTTP/2 用多路复用解决了队头阻塞」,然后被追问「那 HTTP/3 为什么还要换 UDP」,就沉默了。

原因:只记住了「多路复用」这个词,没记住 HTTP/2 底下跑的还是 TCP。

解决:把队头阻塞拆成两层看。HTTP 层的队头阻塞,HTTP/2 确实解决了,靠的是 Stream,一个连接里多个流各走各的,谁先准备好谁先发,接收端按 Stream ID 重新组装。但 TCP 层的队头阻塞还在——TCP 是字节流协议,它必须保证数据完整且连续,前面丢了一个字节,后面的数据只能在内核缓冲区里等着。HTTP/3 之所以把下层换成基于 UDP 的方案,就是为了绕开这一层。

5.2 动手上的两个坑:只看结论不看过程

坑四:DNS 只背流程,分不清递归和迭代。

现象:解析顺序那八步背得挺顺,一问「递归查询和迭代查询有什么区别」,就开始含糊其辞。

原因:两个概念被合在一起记了,没有分清「谁在替谁跑腿」。

解决:站在本地 DNS 服务器的视角问自己一句:这一趟是我自己跑完的,还是我只拿到下一站地址?客户端把活整个托给本地 DNS 服务器,那是递归;本地 DNS 服务器每次只从上层拿到「下一站去哪儿」,然后自己去问,那是迭代。抓住「谁负责跑完全程」这一条,两个词就再也不会混。

坑五:改了缓存配置却怎么都看不到效果。

现象:在服务器上把Cache-Control改短了,浏览器里刷新还是旧的,怀疑自己改错了地方。

原因:强缓存还没过期,浏览器压根就没发请求出去,服务器那边根本不知道你来过。

解决:三招任选——在 Network 面板勾上 Disable cache;开一个无痕窗口测;或者用 curl 带上Cache-Control: no-cache强制走协商。另外记住一个顺序:改完配置先别急着怀疑代码,先确认「请求到底有没有发出去」,这一步能省掉一半的排查时间。

注意:这五条里最耗时间的是坑五。它不属于知识没学会,而是观测手段没跟上。养成「先确认现象,再猜原因」的习惯,比多背十个知识点管用。

6. 下一步学什么:从网络地基往上的四步走法

把这一篇过完之后,很多人会问同一个问题:接下来该学什么。我的建议是别急着横向铺开去啃操作系统和数据库,先把网络这条线夯实,因为它是最容易验证、也最容易在面试里立刻兑现的一块。下面是一个可以参考的顺序。

顺序学什么学到什么程度算过关
1一次完整访问流程合上资料,能不看提示口述七个步骤
2TCP 连接的建立与断开能画出三次握手和四次挥手,说出每一步报文的作用
3HTTP 与缓存能看懂响应头里的缓存字段,讲清强缓存和协商缓存的区别
4HTTP 版本演进与 DNS能说清每个版本解决了上一版的什么问题,DNS 解析链路能讲完整

这四步里,第一步和第二步最值钱。它们占了面试里这类问题的绝大多数,也决定了你后面学东西时有没有地方挂。第三步和第四步属于加分项,面试官问到你能答上来,问不到你也不亏。

方法上,我给三个具体建议。第一个是合上资料复述:每学完一块,合上电脑,用大白话讲一遍,讲卡壳的地方就是没懂的地方,回去补那一块,别从头再看一遍。第二个是动手验证:凡是能用 curl 或者 F12 看到的,就别只停留在看书,前面那几段命令多跑几遍,比读十页解释都管用。第三个是建一张自己的图:不用画得多好看,就把七个步骤和对应的知识点画在一张纸上,学一点补一笔,一个月后这张纸就是你的复习提纲。

最后说个我自己的教训。我第一次准备这块内容的时候,把答案抄了满满几页,合上本子觉得稳了。结果被问了句「第一次握手丢包之后,服务器会分配资源吗」,当场愣住。从那以后我每次学新知识点,都强制走一遍「合上资料,讲给一个完全不懂的人听」——讲得下去才算会,讲不下去就说明还欠火候。这个习惯笨是笨了点,但它救过我很多次。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表