一个网络请求的流程

最新在看《计算机网络–自顶向下方法》,把从应用层到链路层的所有网络协议都重新学习了一遍。这里借用这个标题,来梳理一下相关协议的工作原理和流程,以及各层的协议之间是如何协同工作的。

首先 你得连上Internet吧

当我们连接上一个路由器后,会得到一个ip地址,如果此时你的路由器已经连接到了ISP,那么恭喜你可以开始在网上🏄了。那么这个ip地址到底是咋分配到我们的机器的呢?!!!

DHCP(dynamic host configuration protocol)

动态主机配置协议,运行在网卡,路由器和交换机等网络设备上,主要用来分配ip地址。和其他协议类似,也是以报文的形式进行通信。

当我们的主机发起一个网络连接请求时,DHCP协议会生成一个DHCP报文,并使用UDP传输协议进行传输,该UDP报文会包含一个组播ip(255.255.255.255)的目标地址,组播ip意味着该网段内所有设备都会收到这条UDP报文。此时因为本机还没有分配ip,所以源ip会是0.0.0.0。

上面的UDP报文会被包在以太网帧中进行传输,该以太网帧的目的地址也是一个组播mac地址(FF.FF.FF.FF.FF.FF),所以该帧会被网段内所有设备接收。而该帧的原地址即为本机的mac地址(比如 28:cf:e9:14:d1:0f 这是我的设备的mac地址)。

路由器收到该以太网帧,一层层解析出DHCP报文,然后路由器决定分配一个ip地址给主机(10.236.142.22),于是通过路由器上的DHCP服务器包装一个DHCP的响应报文,把包括了DNS服务器ip,路由器ip,子网掩码和分配给主机的ip一起发送给该主机。因为路由器已经知道了主机的mac地址,所以该报文会顺利的到达。

主机网卡在收到DHCP ACK报文后,解析出相关的ip并配置好网络组件。至此,主机连接Internet成功。

只有域名是不可以的

连上Internet后,我们就可以上google了。于是我们在浏览器上输入www.google.com,也就是google的域名,不包括前面的www(www是一个网络应用,中文名叫万维网)。而google的主页应该是放在服务器上的,通过域名是如何访问到服务器上的google主页的呢?!!!

DNS(domain name system)

DNS主要用来查询域名对应的ip地址。和DHCP一样,DNS报文使用UDP进行传输。DNS报文将www.google.com放入报文段,然后组装成UDP报文,在上面的DHCP ACK中,已经拿到了DNS的ip,所以在组装ip报文的时候目的ip直接使用dns的ip,源ip则为主机的ip。

之后,ip报文会被放到以太网帧中进行传输,想要将dns报文发送到dns服务器,首先第一个难题就是如何传送到所在网络的网关路由器,在上面的DHCP ACK报文中,已经拿到了网关路由器的ip了,但是ip只是作用在网络层,如果没有mac地址,链路层上是无法传输的。

ARP(address resolution protocol)

地址解析协议,通过一个ip地址获取mac地址。ARP使用网关路由器的ip地址生成一个ARP查询报文,然后将该报文放到目标地址为(FF.FF.FF.FF.FF.FF)的以太网帧上,因为是广播地址,所以网关路由器顺利收到该帧,并生成一个ARP的回答报文,报文中带上了网关路由器的mac地址。然后将回答报文放到目的地址为主机mac地址的以太网帧中,这样,我们就顺利的拿到了网关路由器的mac地址。

通过ARP,dns查询报文顺利的发送到了网关路由器。之后,又该何去何从?!!!

BGP(broder gateway protocol)

边界网关协议,AS(自治系统)之间的路由选择协议,BGP极其复杂,许多专著致力于研究该主题,它的基本工作流程是:

  • 从相邻AS处获取子网可达性信息
  • 向本AS内部的所有路由器传播这些可达性信息
  • 基于可达性信息和AS策略,决定到达子网的最优路由

我们还得回到最上面的DHCP ACK中去,因为DNS的ip地址是这个报文给返回的,那么它又是如何生成该ip的呢。其实这个ip并不是它生成的,是ISP提供的。当路由器连接上ISP以后,对应的路由转发表会进行更新,所以dns的ip对应的转发接口已经存在于路由转发表中(根据BGP边界网关协议),至此,dns查询报文被发送到对应的dns服务器上。

dns服务器接收到查询报文后,开始根据域名在缓存中查找对应的ip,如果缓存中没有找到,会去到ISP的权威dns服务器上查找,如何还找不到,会去到.com对应顶级dns服务器上查找,如果还是没有找到,会到跟域名服务器上查找,如果根域名上也没有找到,则返回查询失败。如果在其他dns服务器上成功找到对应的ip,该服务器会先缓存到本地,然后生成一个UDP的DNS回答报名,发送到对应的主机上,至此,我们终于拿到了google.com对应的ip地址。接下来我们要开始发送http的get请求了。

顺理成章的http请求

拿到ip后,http客户端会生成一个get请求,然后封装到tcp的报文中。tcp在进行数据传输前,会有一个三次握手的过程,握手成功后,get请求的报文成功被google的服务器接收,然后服务器通过url找到对应的资源,生成一个http的响应报文并封装在tcp的报文中,然后发送给客户端。

因为已经建立了连接,所以响应报文不在需要握手的流程,客户端顺利收到响应报文,并解析出资源数据,将数据丢给浏览器进行显示(浏览器如何解析数据并渲染的流程不在这篇文章的讨论范围之内)。。。

因为http并不是长链接(1.1以后才支持),所以在一个http请求结束后,客户端还是发起一个断开链接的操作,也称四次挥手的过程。至于断开连接为啥会比建立连接多一次握手过程,就留给读者自己去比较和分析吧。

总结

至此 一个完整的网络请求就总结完毕了,当然,这只是一个大概的流程总结,重点介绍和DHCP和链路层相关的几个协议,tcp和ip协议因为之前已经总结过所以这里只是一笔带过。如果想要了解得更为深入的话,当然推荐大家看一下《TCP/IP详解》系列书籍和我正在看的这本《计算机网络–自顶向下方法》书了。