Skip to main content

一台电脑从联网到看到网页全过程的技术细节

场景设定:我,买了台新电脑,准备连学校网络,然后上Google首页(假设没有墙)。电脑第一次连学校网络,没有任何缓存。

整个场景涉及到的节点包括(按连接顺序):

  • 我的电脑,
  • 学校的以太网交换机,
  • 学校网络的网关路由器,
  • ISP + DNS服务器(由ISP提供),
  • 谷歌的权威DNS服务器,谷歌的web服务器。

下面开始。

本机IP地址分配:DHCP协议#

我的电脑还没有分配IP地址,所以需要先运行DHCP协议,从本地的DHCP服务器获得一个IP地址和其他信息。准备广播DHCP报文,报文封装过程:

  • DHCP请求报文 +=>
  • UDP报文 with 目的地端口67(DHCP服务器)+源端口68(DHCP客户)+=>
  • IP数据报文 with 广播IP目的地地址(255.255.255.255)+源IP地址(0.0.0.0) +=>
  • 以太网帧 with 目的MAC地址(FF:FF:FF:FF:FF:FF)+源MAC地址(我的电脑的MAC地址)

然后在以太网中广播该帧。

路由器接收到该以太网帧后,逐层分解数据包,分配IP地址,准备打包DHCP ACK报文:

  • DHCP ACK报文 with 分配的IP地址+DNS服务器的IP地址+默认网关路由器的IP地址+子网块(网络掩码) +=>
  • UDP报文 +=>
  • IP数据报文 +=>
  • 以太网帧 with 源MAC地址(之前接受到以太网帧接口的MAC地址)+目的MAC地址(我的电脑的MAC地址)

准备发回。因为交换机的自学习特性,所以知道寻址到我的电脑的MAC的帧就是从我的电脑的网口发出的。

我的电脑接收到DHCP ACK报文之后,分解当中的信息,初始化电脑的网络组件,比如记录自己的IP地址、DNS服务器的IP地址等。

目标网站IP地址转换:DNS协议#

我的电脑准备生成TCP socket,向google.com发送HTTP请求。但在这之前,我的电脑要先知道google.com的IP地址。为此需要使用DNS协议

我的电脑准备生成DNS查询报文,封装过程如下:

  • DNS报文 with 问题段(google.com) +=>
  • UDP报文段 with 目的端口53(DNS服务默认端口) +=>
  • IP数据包 with IP目的地址(DNS服务器的IP地址) +=>
  • 以太网帧 with 目的地址(之后要得到的网关路由器的MAC地址)

准备发送,在链路层寻址后发送到学校网络的网关路由器。但此时我的电脑还不知道学校网关路由器的MAC地址,虽然经过之前的DHCP协议已经知道了网关路由器的IP地址(真的是坑人啊)。所以在发DNS报文之前,要先进行下面的ARP协议。

MAC地址查询:ARP协议#

照例准备报文:

  • ARP查询报文 with 目的IP地址(网关路由器的IP地址) +=>
  • 以太网帧 with 广播目的地址(FF:FF:FF:FF:FF:FF)

然后向交换机发送该以太网帧,交换机把该帧交付给所有连接的设备,包括网关路由器。网关路由器接收到该帧时,发现目的IP地址与自身的IP地址匹配,于是开始准备ARP应答,提供自己的MAC地址,封装到一个以太网帧,其中目的IP地址为我的电脑的IP地址,再次发给交换机转发。

我的电脑收到ARP应答之后,分解得到学校网关路由器的MAC地址。现在,前面那个包含DNS查询的以太网帧可以寻址到网关路由器了。我的电脑向交换机发送该帧,交换机将其转发给网关路由器。

DNS服务器选择#

网关路由器在接收到DNS查询的报文之后,根据转发表,把报文转发到ISP的网关路由器。后者再将报文转发到DNS服务器,开始逐层地查找DNS记录。当找到包含对应google.com的IP地址的DNS源记录之后,服务器准备一个包含主机名到IP地址映射的DNS回答报文,发回我的电脑。

至此我的电脑得到了google.com的IP地址。

TCP/HTTP交互#

现在可以生成TCP socket了。之后首先进行“三次握手”:

  • 生成TCP SYN报文段,放置到目的IP地址为google.com的IP地址的IP数据报中,再放置到MAC地址为学校网关路由器MAC地址的帧中,向交换机发帧;
  • TCP SYN经由交换机、学校网关路由器、ISP路由器、谷歌网络路由器,根据各自的转发表,最终转发到google.com所在的web服务器。后者分解出TCP SYN报文,生成一个与我的电脑连接的socket,生成TCP SYNACK报文,类似地发回到我的电脑,把TCP SYNACK分解到我的socket。
  • 我的电脑再向服务器发送一个确认报文,至此完成建立TCP连接。

现在可以发送HTTP GET请求来获取网页内容了。我的电脑的浏览器生成一个HTTP GET报文,写入socket,GET报文将成为一个TCP报文段的负载,TCP报文段再放进一个IP数据报文,发给web服务器。

web服务器收到报文,生成一个HTTP响应报文,其中HTTP响应体是网页内容,然后将报文发回。

我的电脑的浏览器收到响应报文之后,分解出其中的网页内容,开始渲染。

至此,网络部分的传送细节已经结束。

而之后浏览器渲染网页的过程属于前端开发的范畴,而非计网课程的内容,有机会再开一篇推文来写。

(后续1:分层网络每层对应的协议)

(后续2:浏览器渲染网页过程)

(未完待续)

本文大部分内容来自《计算机网络:自顶向下方法》(第六版),当然还有龙博的上课讲解。

之前自学前端的时候关注这个问题很久了,但由于还没上过计网课,所以知识点很零散。现在终于快上完计网课了,刚好老师也很着重强调这个问题,在课程尾声总结了一轮,还布置了课后作业。借此机会再自己总结一下。