当你浏览一个网页时,协议栈中发生了什么?

Posted by 刘知安 on 2019-06-16
文章目录
  1. 说在前面的话
  • 详细流程
    1. 第一关——主要通过DHCP来得到一个本机IP地址
    2. 第二关——DNS协议和ARP协议
    3. 第三关——路由选择到DNS服务器
    4. 最后一关—— Web客户端和服务器交互:TCP和HTTP
  • 说在前面的话

    下面的例子是来自与计算机网络自顶向下方法,根据书上的描述、我的理解以及一些相应的修改,进行回顾总结。

    场景:用户Bob有一个笔记本电脑,他用网线连接到学校实验室的网络,然后准备访问谷歌(www.google.com),假设学校的网络是接在了一个ISP上,该ISP又和google的网络是相连的,同时,DNS服务由该ISP提供,DHCP服务(后面会提到)由学校路由器提供,Bob的笔记本通过交换机和学习的路由器互联,场景图示如下:
    在这里插入图片描述

    详细流程

    假设最开始Bob的计算机对网络的信息什么都不知道(即从来没做过任何关于网络信息的缓存),那么Bob访问google主页会经历以下步骤:

    第一关——主要通过DHCP来得到一个本机IP地址

    • (1)Bob的笔记本一开始是没有IP地址的,没有IP地址,也就没办法上Internet。于是,将利用DHCP(Dynamic Host Configuration Protocol)动态主机配置协议请求从DHCP服务器那边分到一个IP地址。笔记本上的操作系统将生成一个DHCP报文,并将这个报文放入一个UDP报文中(DHCP协议是建立在UDP协议上的哈),该UDP报文的目的端口是67(DHCP服务器的端口),源端口是68(Bob笔记本的端口)。由于此时这台笔记本还没有被分到一个具体的IP,而UDP报文肯定又要封装到IP数据报中,于是这时的IP数据包的源IP地址是0.0.0.0(表示本网络),目的IP地址是255.255.255.255(广播)
    • (2)包含DHCP请求报文的IP数据报又被封装在以太网帧(假设链路层用的是以太网)中,该以太网帧具有的源MAC地址是00:16:D3:23:68:8A(Bob笔记本网卡的MAC地址),目的MAC地址是FF:FF:FF:FF:FF:FF(广播),为什么这里需要广播呢?因为客户端(Bob的笔记本)也不知道自己所处的局域网中到底由哪台机器来提供DHCP服务,所以自然就把DHCP请求向各个机器都发一遍,相当于一个一个问,诶,兄弟,你能给我分个IP地址吗?A机器说,不能,滚!它又去问机器B…就这样一直问下去
    • (3)为了达到上述的以太网帧广播的目的,实际上是Bob的计算机先把这个包含DHCP的以太网帧(中间依次又封装了UDP报文、IP报文)发送到该计算机连接到的交换机,交换机向所有连接到的机器广播该以太网帧。
    • (4)我们假设学校的路由器提供DHCP服务。因为这个路由器又是连接在交换机上的,自然就会收到上述包含Bob计算机DHCP请求的以太网帧了,则路由器在它的具有MAC地址为00:22:6B:45:1F:1B的接口上接受到DHCP请求的以太网帧,并从中抽出IP数据报,还记得第(1)步中Bob计算机发送的IP报的目的IP地址吗?——对,255.255.255.255,这样一来,路由器解析到了该目的IP,就知道这个数据报应当由该结点的上层协议来处理,于是该IP报的数据段中的UDP报文会被分解,路由器上运行的DHCP服务程序(绑定在67号端口上)会从该UDP报文中解析出DHCP请求报文,然后做分配IP的操作。
    • (5)假设学校路由器上的DHCP服务器能够在CIDR块68.85.2.0/24的一堆网络IP中给Bob的笔记本分配一个IP68.85.2.101,而学校的这个CIDR块又是从ISP Comcast那边68.80.0.0/13分到的一小块。然后DHCP服务器会生成一个包含分出来的IP地址(68.85.2.101)、DNS服务器的IP地址(68.87.71.226)、默认网关路由器的IP地址(68.85.2.1)、子网块(68.85.2.0/24相当于子网掩码)的DHCP ACK报文,这个报文又会被封装进UDP报文,从而封装进IP数据报,从而封装进以太网帧中,该以太网帧具有的源MAC地址是00:22:6B:45:1F:1B(路由器一个接口的MAC地址),目的MAC地址是00:16:D3:23:68:8A,这个目的MAC地址就是从包含DHCP请求报文的以太网帧中解析出来的哈。

    说明一下,因为学校这块局域网中只有一个路由器,所以默认网关也肯定只能是这个路由器了

    • (6)包含DHCP ACK报文的以太网帧由路由器发给交换机,由于交换机这个东西呢,它有个所谓的自学习特性,其实就是说,交换机会从每次交换的以太网帧中提取到源主机的MAC地址,然后记录到一张交换表中(学习过程),万一有一个MAC地址没在交换表中呢(没学习到)?—— 对了,简单粗暴,广播给所有接入的机器上去。 由于之前Bob的笔记本在发送DHCP请求报文的时候经过了一次交换机,所以它的MAC地址(也就是DHCP ACK报文的目的MAC地址)肯定会被学习到。然后交换机就将路由器那边发过来的DHCP ACK报文直接转发给Bob的笔记本了
    • (7)Bob的笔记本接受到DHCP ACK报文,然后就会像DHCP服务器那样依次解析出DHCP报文中的信息,然后把各个字段(分到的IP地址、DNS服务器地址、默认网关地址、子网掩码这些)解析出来,然后把本机的配置改一下。

    呼。。。。这么一大通操作下来,Bob的算是通网了,离着访问google更近了一步。

    第二关——DNS协议和ARP协议

    Bob打开浏览器,在地址栏里面输入:www.google.com

    • (8)我们知道,域名肯定是要对应到它的IP地址才能进行通信的,于是Bob的操作系统因此生成一个DNS(Domain Name System)查询报文(这个协议也是基于UDP协议的),于是www.google.com这个URL被放进了DNS报文的问题段中,且该DNS报文的目的端口是53(DNS服务器),这个DNS报文被封装进UDP报文中,UDP报文的源IP是68.85.2.101目的IP是68.87.71.226(DHCP ACK报文中已经获取到)
    • (9)上一步包含DNS请求报文的数据报被放入一个以太网帧中,好了,这个帧即将转发到学校的路由器上去,然后再通过中间一些列路由器转发到DNS服务器上去(当然,这个过程对客户端来说是透明的)。!!!等等!!!,好像有点不对大头,这个以太网帧的目的MAC是什么???目前Bob的笔记本是知道网关的IP地址的,可是不止到网关的MAC地址呀!这样一来,就不知道让交换机转发给谁了。 是的,这个时候ARP(Address Resolution Protocol)地址解析协议就派上用场了。
    • (10)Bob的笔记本生成一个ARP查询报文,该报文的目的IP地址是68.85.2.1,也就是默认网关,因为不知道那个网关IP对应的MAC地址嘛(也正是我们想要得到的),没办法,被逼无奈,只能用最简单粗暴的方法了——广播。老铁再一次逐个询问(挨个问交换机出口的所有机器),你的IP地址是不是68.85.2.1啊?是的话,麻烦你把你的MAC地址告诉我一下,我想送点东西到你家里去,要不然我找不到你。 是的,和上面说到的DHCP请求报文类似,这里也会生成一个目的地址为FF:FF:FF:FF:FF:FF的以太网帧,交换机会广播出去。
    • (11)交换机出端口这边的所有机器都收到了广播以太网帧,而只有网关路由器发现,自己的IP地址和这个封装了ARP请求报文的帧中的目的IP地址匹配,于是就把自己的MAC地址封装进一个ARP回答报文中(它估计是有人有好事要找他了,呵呵),然后把这个ARP回答报文封装进一个以太网帧中,该帧的源MAC地址是00:22:6B:45:1F:1B(路由器一个接口的MAC地址),目的MAC地址是00:16:D3:23:68:8A,并将该帧发送给交换机,交换机发给Bob的笔记本。

    细心的你可能会发现,诶,这个帧的目的和源地址好像和之前DHCP ACK报文一样啊!是的,回顾一下说在前面的话,我们假设DHCP服务是在学校路由器上提供的,于是这里就产生了一个目的和源MAC地址一样的帧。但是实际情况中,DHCP服务器可能和默认网关服务器不是在同一台机器上(所以,你可以认为这是凑巧吧。)

    • (12)Bob的笔记本收到了上述包含ARP回答报文的帧,并从中解析出默认网关的MAC地址(00:22:6B:45:1F:1B
    • (13)现在Bob的笔记本知道了默认网关的MAC地址了,于是在第(9)步中的问题解决了,封装DNS查询请求的以太网帧终于可以通过交换机转发到默认网关那边去了,至于默认网关路由器再怎么转发这个DNS查询报文,对不起,Bob的笔记本就不管那么多了。

    第三关——路由选择到DNS服务器

    • (14) 网关路由器接受到交换器转发过来的包含DNS查询报文的以太网帧,并从中抽取出IP数据报,路由器找到IP数据报中的目的IP地址68.87.71.226,并根据路由器中的转发表知道应该发送到ISP提供方的最左侧的那个路由器上去(这里可能会涉及到不同自治域之间的路由选择协议),然后把原以太网帧进行相应修改并发送出去(这里会把最初始的MAC源地址和目的地址进行变换哈)
    • (15)在Comcast网络中,最左边的路由器接收到该帧后,抽取IP数据报文,发现目的地址是68.87.71.226(DNS服务器),于是它根据域内路由选择协议(RIP或OSPF等)将数据报继续向下一站转发。
    • (16)最终,包含DNS查询的IP数据报到达了DNS服务器,DNS服务器从中抽取出DNS查询报文,发现客户端是想查询www.google.com的IP地址,服务器于是从本地文件系统(文件或数据库中)从查询到谷歌的IP地址,生成一个DNS回答报文,并将之封装进UDP报文中,然后发回到Bob的笔记本。

      这里发回的过程和Bob发送的过程刚好完全相反

    • (17)Bob的笔记本接受到DNS回答报文,然后从中解析出了www.google.com的IP地址,准备开始接触谷歌服务器了!

    最后一关—— Web客户端和服务器交互:TCP和HTTP

    • (18)假设Web客户端希望发送一个HTTP GET请求,请求到www.google.com页面,为了达到此目的,客户端好服务器之间要建立TCP连接(HTTP是面向连接的协议),准备开始三次握手过程。于是Bob的笔记本首先生成一个目的端口为80(服务器HTTP端口)TCP SYN(TCP连接报文),该TCP报文放置在具有目的IP地址为64.233.169.105(www.google.com DNS回复报文中所得)的IP数据报中,并将该数据包放在MAC地址为00:22:6B:45:1F:1B(网关路由器的MAC地址)的以太网帧中,并向交换机发送该帧
    • (19)经过一些列的路由器转发,包含TCP SYN的数据包到达谷歌服务器,服务器分解报文,并将之分解到与80端口联系的欢迎套接字,然后谷歌HTTP服务器和Bob笔记本之间的TCP连接生成一个连接套接字,产生一个TCP SYN ACK报文,并将之发回到Bob的笔记本(和TCP SYN报文刚好相反)
    • (20)Bob笔记本收到TCP SYN ACK报文,并且生成一个ACK报文确认收到服务器端的响应,此时三次握手完毕,客户端和服务端之间建立好了连接。
    • (21)包含HTTP GET请求的HTTP报文被封装进TCP报文中,从Bob笔记本传往谷歌HTTP服务器。
    • (22)谷歌HTTP服务器收到TCP报文后,解析出报文内容,知道客户端想要得的www.google.com的内容,于是将该页面的HTML内容封装进TCP报文中作为响应,发送回Bob的笔记本。
    • (23)Bob的笔记本收到HTTP 响应报文,交给浏览器,解析出其中的HTML内容,显示网页内容!

    以上所有的步骤,就是浏览一个网页时,协议栈中发生的事情。

    如有错误,请留言指明。