Administrator
发布于 2025-11-08 / 10 阅读
0
0

访问www.baidu.com的过程

这个过程本质上就是:一个客户端如何通过一系列约定好的协议(接口规范),定位并调用一个远端服务,最终获取到计算资源(HTML页面)。

核心思想:协议栈就是一套分层的API

我们可以把整个网络栈看作一套设计精良的库或框架,每一层都为上层提供清晰的API接口,并依赖下层的服务。

应用层 (HTTP/HTTPS): 你的“业务逻辑”。你关心的是 GET / 这个操作和返回的HTML数据。

安全层 (TLS): 一个负责加密通信的“中间件”。它接管了应用层的数据,加密后交给传输层。

传输层 (TCP): 一个保证“可靠交付”的“服务”。它不关心数据内容,只关心数据有没有完整、顺序正确地送到。

网络层 (IP): 一个负责“全局寻址和路由”的“基础设施”。它负责把数据包从一个设备 hop-by-hop 地送到另一个设备。

链路层 (Ethernet, ARP): 负责在“本地局域网”这个“总线”上,把数据帧传给下一个节点(比如你的路由器)。

现在,我们按照调用顺序来走一遍。

第一步:服务发现 —— DNS查询 ( over UDP )

你想调用 www.baidu.com 的服务,但你的系统只知道它的域名,不知道它的IP地址(相当于只知道服务名,不知道具体的主机端口)。所以第一步是服务发现。

本地缓存查询:就像你本地有一个 Map<ServiceName, Address>。浏览器缓存 -> 操作系统缓存(/etc/hosts 或 C:\Windows\System32\drivers\etc\hosts) -> 路由器缓存。这里是第一层优化,命中则直接返回。

递归/迭代查询:如果缓存未命中,就要向“服务注册中心”——也就是你配置的DNS服务器(如 8.8.8.8)发起查询。这里用的主要是 UDP 协议。

为什么是UDP? 因为DNS查询通常是“一问一答”的短平快操作。建立TCP连接的三次握手成本太高了。UDP无连接、开销小的特性正合适。只有当返回的应答数据太大(超过512字节),才会降级使用TCP。

过程:你的请求会经过一个可能很长的链条(本地DNS -> 根域名服务器 -> .com顶级域名服务器 -> baidu.com的权威域名服务器),最终拿到IP,比如 14.119.104.254。

至此,服务地址找到了。

关键点: DNS用UDP,是为了性能。它是一个简单的请求-响应模型,无需维护连接状态。只有当返回数据太大(超过512字节),才会自动降级到TCP。

第二步:建立可靠传输通道 —— TCP三次握手

现在你知道目标IP了,要发起真正的“业务请求”了。但你的业务(HTTP)需要可靠的传输,不能丢包、乱序。所以你选择了TCP这个“可靠传输服务”。

  • TCP三次握手,本质上是一个确保“双方都具有收发能力”的同步过程:

SYN (Synchronize Sequence Numbers): 客户端发送一个SYN包,带上初始序列号 seq=x。意思是:“老哥,我想跟你建立连接,我这边收发的起始号是x,你听得到吗?”

SYN-ACK: 服务端收到后,回复一个SYN-ACK包。ACK是 x+1,表示“你发的x我收到了,下一个我期待x+1”。同时,服务端也带上自己的初始序列号 seq=y。意思是:“我听到了,我这边准备好了,我的起始号是y。”

ACK (Acknowledgment): 客户端再回复一个ACK包,ACK是 y+1。意思是:“好的,你的y我也收到了,接下来就从y+1开始。”

  • 为什么是三次?不是两次?

这是一个经典的分布式系统共识问题。两次握手只能保证客户端确认了服务端的收发能力,服务端确认了客户端的发送能力,但服务端无法确认客户端的接收能力是否正常。如果第二次握手(SYN-ACK)的包丢了,服务端会认为连接已建立,开始发数据,但客户端根本没准备好,会造成资源浪费和混乱。

三次握手后,一个全双工的、可靠的字节流通道就建立好了。 这就像在两个进程之间拉起了一根可靠的管道。

第三步:建立安全上下文 —— TLS握手

因为现在是 https,你需要在发送明文HTTP请求之前,先在这根TCP管道上套一个“加密壳”。TLS握手就是在协商这个“壳”的加密方式和解密钥匙。

  • 这个过程可以类比为双方在建立一套“暗号系统”:

ClientHello: 客户端联系服务端,说:“我支持这些加密套件(比如 TLS_AES_128_GCM_SHA256),这是我的随机数 Random_C。”

ServerHello + Certificate: 服务端选择一套加密套件,回复说:“我们就用 TLS_AES_128_GCM_SHA256 吧,这是我的随机数 Random_S,还有我的身份证(证书),你验一下。” 证书里包含了百度的公钥。

验证证书: 客户端(浏览器)用内置的CA(证书颁发机构)公钥去验证服务端证书的合法性(签名、有效期、域名等)。这是整个HTTPS安全的核心,防止中间人攻击。

Pre-master Secret: 客户端生成一个预主密钥,用服务端的公钥加密,发过去。只有拥有对应私钥的服务端才能解密。

生成会话密钥: 此时,客户端和服务端都拥有了 Random_C, Random_S, 和 Pre-master Secret。它们用同样的算法,独立生成出相同的主密钥,进而派生出用于本次会话的对称加密密钥。

  • 为什么最后用对称加密?

因为非对称加密(RSA等)计算开销巨大。TLS巧妙地用非对称加密安全地交换了对称加密的密钥,后续通信则用计算更快的对称加密来保护数据。

至此,一个安全的、加密的通道在TCP通道之上建立完毕。

第四步:发起业务请求 —— HTTP

现在,万事俱备。你的“业务逻辑”——HTTP请求,终于可以通过这个安全可靠的通道发出去了。

构建HTTP请求:浏览器组装一个HTTP请求报文。

GET / HTTP/1.1

Host: www.baidu.com

User-Agent: Mozilla/5.0 (...)

Accept: text/html,application/xhtml+xml,...
(还有Cookie等一大堆Header)

发送与接收:这个文本报文被TLS层加密成乱码,然后被TCP层拆分成多个Segment(如果大的话),加上TCP头,交给IP层。IP层打包成Packet,加上IP头,交给链路层... 最终送到服务器。

服务器处理:服务器端的协议栈逐层解包,TLS解密,最终还原出HTTP请求。Web服务器(如Nginx)和处理程序(如后端API)处理这个请求,生成HTML页面。

返回响应:服务器同样沿着协议栈,将HTTP响应(200 OK, 后面跟着HTML数据)加密、分包,传回给你的浏览器。

第五步:渲染与连接管理

浏览器渲染:浏览器拿到HTML后开始解析,构建DOM树。遇到CSS、JS、图片等外部资源时,会重复上述所有步骤去获取它们。不过,现代浏览器会复用已经建立的TCP连接(HTTP/1.1的Keep-Alive),或者使用HTTP/2的多路复用来并行请求,极大提升效率。

关闭连接:在数据交换完毕后,最终会通过 TCP四次挥手 来优雅地关闭连接。这又是一个确保数据完整性的双向关闭协议。

附件:www.baidu.com引发的思考.vsdx


评论