说在前面的话
下面的例子是来自与计算机网络自顶向下方法,根据书上的描述、我的理解以及一些相应的修改,进行回顾总结。
场景:用户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内容,显示网页内容!
以上所有的步骤,就是浏览一个网页时,协议栈中发生的事情。
如有错误,请留言指明。