题目
输入URL按下回车后,中间发生了什么
这个问题其实是计算机网络里面很经典的一个问题,不能去死机硬背,很考察对网络架构和通信原理的理解,也是各个互联网大厂喜欢考察的面试题。
一些图片参考了小林的计算机网络面经
从输入网址到确定,用户其实是无感的,因为这个中间事件正常时一秒钟不到。但是在计算机的底层却发生了很多的变化。
因特网的架构是基于TCP/IP的,所以我也从TCP/IP去分析这个过程。
整个互联网的拓扑架构:数据报离开了本地的,中间需要经历多个交换机、路由器。
TCP/IP
首先得回顾一下tcp/ip的架构。每一层的基本协议包括:
TCP/IP协议的核心在于网络层和传输层。
分析
URL->IP
输入URL访问南京工程学院,发生在应用层,是应用层之间的操作。
我们知道路由器转发数据包时根据数据包的目的IP地址来转发的,所以需要知道南京工程学院的IP地址,这个如何解决呢?
依靠了应用层的DNS解析,本地电脑会通过DNS解析来将URL转为对应的IP地址。
DNS本质上是一个分布式数据库,里面存着一张二维表格,域名和IP是一一对应的关系,底层用b+树索引,便于快速检索需要的ip地址。
首先会在本地DNS缓存服务器里面找有没有,如果没有就向根域名服务器发送请求。有两种查询方式一种是迭代查询、另一种是递归查询。
拓展DNS请求的过程所用的是UDP协议。
产生请求消息
请求的内容会变为HTTP报文,本地向服务器发送的是http报文。
http分为get请求和post请求。
到达传输层
因特网的网络层给上层提供的不可靠的服务,所有的压力都给了传输层。
TCP具有:流量控制、拥塞控制、滑动窗户。为了保证传输的安全,传输之前要建立三次握手,结束后需要进行四次挥手。
UDP可以用来广播,它是不可靠的。
TCP的报文格式:
首先,源端口号和目标端口号是不可少的,如果没有这两个端口号,数据就不知道应该发给哪个应用。
接下来有包的序号,这个是为了解决包乱序的问题。
还有应该有的是确认号,目的是确认发出去对方是否有收到。如果没有收到就应该重新发送,直到送达,这个是为了解决丢包的问题。
接下来还有一些状态位。例如 SYN 是发起一个连接,ACK 是回复,RST 是重新连接,FIN 是结束连接等。TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。
还有一个重要的就是窗口大小。TCP 要做流量控制,通信双方各声明一个窗口(缓存大小),标识自己当前能够的处理能力,别发送的太快,撑死我,也别发的太慢,饿死我。
除了做流量控制以外,TCP还会做拥塞控制,对于真正的通路堵车不堵车,它无能为力,唯一能做的就是控制自己,也即控制发送的速度。不能改变世界,就改变自己嘛。
建立连接进行三次握手:
一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态。
然后客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。
服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,之后处于 SYN-RCVD 状态。
客户端收到服务端发送的 SYN 和 ACK 之后,发送对 SYN 确认的 ACK,之后处于 ESTABLISHED 状态,因为它一发一收成功了。
服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。
所以三次握手目的是保证双方都有发送和接收的能力
TCP还会进行数据分割:
如果 HTTP 请求消息比较长,超过了 MSS 的长度,这时 TCP 就需要把 HTTP 的数据拆解成一块块的数据发送,而不是一次性发送所有数据。
MTU:一个网络包的最大长度,以太网中一般为 1500 字节。
MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。
数据会被以 MSS 的长度为单位进行拆分,拆分出来的每一块数据都会被放进单独的网络包中。也就是在每个被拆分的数据加上 TCP 头信息,然后交给 IP 模块来发送数据
TCP 协议里面会有两个端口,一个是浏览器监听的端口(通常是随机生成的),一个是 Web 服务器监听的端口(HTTP 默认端口号是 80, HTTPS 默认端口号是 443)。
在双方建立了连接后,TCP 报文中的数据部分就是存放 HTTP 头部 + 数据,组装好 TCP 报文之后,就需交给下面的网络层处理
报文格式如下:
到达网络层
首先将自己的ip地址封装到数据包里面。
网络层有ARP和ICMP协议。
ICMP 用于告知网络包传送过程中产生的错误以及各种控制信息。
ARP 用于根据 IP 地址查询相应的以太网 MAC 地址
为什么要mac地址
ip地址只能定位,就像可以找到你住的小区一样,而只有MAC地址才能确定一个人的身份信息。所以到了小区里面就要找到MAC地址,这个过程用了ARP协议,通过广播的形式找到目标的MAC地址,回来时单播的形式。
在后续操作系统会把本次查询结果放到一块叫做 ARP 缓存的内存空间留着以后用,不过缓存的时间就几分钟。
现在的报文格式:
出口
通过网际接口层,数据包内全是一串的二进制数字信息,没有办法直接发送给对方,因此需要将二进制全部转为电信号才能在网线上传输。
负责这个操作的时网卡。
中间的长途慢慢
交换机
首先,电信号到达网线接口,交换机里的模块进行接收,接下来交换机里的模块将电信号转换为数字信号。
然后通过包末尾的 FCS 校验错误,如果没问题则放到缓冲区。这部分操作基本和计算机的网卡相同,但交换机的工作方式和网卡不同。
计算机的网卡本身具有 MAC 地址,并通过核对收到的包的接收方 MAC 地址判断是不是发给自己的,如果不是发给自己的则丢弃;相对地,交换机的端口不核对接收方 MAC 地址,而是直接接收所有的包并存放到缓冲区中。因此,和网卡不同,交换机的端口不具有 MAC 地址。
将包存入缓冲区后,接下来需要查询一下这个包的接收方 MAC 地址是否已经在 MAC 地址表中有记录了。
交换机的 MAC 地址表主要包含两个信息:
一个是设备的 MAC 地址,
另一个是该设备连接在交换机的哪个端口上。
举个例子,如果收到的包的接收方 MAC 地址为 00-02-B3-1C-9C-F9,则与图中表中的第 3 行匹配,根据端口列的信息,可知这个地址位于 3 号端口上,然后就可以通过交换电路将包发送到相应的端口了。
所以,交换机根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端口。
地址表中找不到指定的 MAC 地址。这可能是因为具有该地址的设备还没有向交换机发送过包,或者这个设备一段时间没有工作导致地址被从地址表中删除了。
这种情况下,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。
路由器
网络包经过交换机之后,现在到达了路由器,并在此被转发到下一个路由器或目标设备。
这一步转发的工作原理和交换机类似,也是通过查表判断包转发的目标。
不过在具体的操作过程上,路由器和交换机是有区别的。
因为路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址;
而交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址。
路由表:
具体的工作流程根据上图,举个例子。
假设地址为 10.10.1.101 的计算机要向地址为 192.168.1.100 的服务器发送一个包,这个包先到达图中的路由器。
判断转发目标的第一步,就是根据包的接收方 IP 地址查询路由表中的目标地址栏,以找到相匹配的记录。
路由匹配和前面讲的一样,每个条目的子网掩码和 192.168.1.100 IP 做 & 与运算后,得到的结果与对应条目的目标地址进行匹配,如果匹配就会作为候选转发目标,如果不匹配就继续与下个条目进行路由匹配。
如第二条目的子网掩码 255.255.255.0 与 192.168.1.100 IP 做 & 与运算后,得到结果是 192.168.1.0 ,这与第二条目的目标地址 192.168.1.0 匹配,该第二条目记录就会被作为转发目标。
实在找不到匹配路由时,就会选择默认路由,路由表中子网掩码为 0.0.0.0 的记录表示「默认路由」
到了服务器
开始相互扒皮,从发送端开始往下是不断地封装,到接收端从下到上不断地扒皮。将所有地全部脱光后,只剩下HTTP数据。http携带的get或者post请求再访问服务器上面的资源,得到资源后,按照上面同样的操作再发给客户端。
最后,客户端要离开了,向服务器发起了 TCP 四次挥手,至此双方的连接就断开了。