网络基础(一次完整的网络请求生命周期)

客户端发起请求
以访问百度为例,用户在浏览器输入www.baidu.com。用户输入的www.baidu.com仅仅是一个域名,这时候计算机并不清楚需要去哪里访问到响应的资源。这时候就需要通过DNS协议来对域名进行解析,从DNS服务商中取得与域名相对应的IP地址。从而通过HTTP协议或者HTTPS协议,打包请求头和请求体向IP地址发起请求。
DNS,HTTP,HTTPS所在的层为应用层,经过应用层的封装后,浏览器将包交由下一层来进行处理,这个过程是通过socket编程来实现的。下一层即是传输层,传输层主要有两种协议。一种是无连接的UDP协议,一种是面向连接的TCP协议。UDP协议不需要建立连接即可进行通讯,不需要额外的性能开销,传输速度更快,但是不可靠,可能会发生丢包的情况。TCP协议需要通过三次握手来建立连接才可以进行通信,相对来说有额外的性能开销,传输速度低于UPD,但是TCP能保证数据到底目的地,更加安全以及可靠。HTTP以及HTTPS都是基于TPC协议的可靠连接。TCP协议中有两个主要端口,一个是基于浏览器的端口(用于监听服务器的响应),一个是基于服务器的端口,HTTP对应的端口为80,HTTPS对应的端口为443,主要用于监听对服务器的请求。操作系统会根据端口将包转发给相应的处理进程。
传输层封装完毕后会讲包交给操作系统的网络层,网络层的基本协议是IP协议,网络层会将传输层传递过来的包加上IP头,其中包含发送方的IP地址,以及接收方的IP地址。操作系统得到IP头中的IP地址后会寻找目标地址,如果服务端的IP地址是内网地址(局域网),便会直接传递请求数据。如果是外网的就需要通过网关去寻找目标机器。操作系统在启动的时候会通过DHCP协议来配置计算机的IP地址,以及默认的网关地址。计算会通过ARP协议通过IP地址获取网关的MAC地址,并且将网关以及MAC地址写到MAC头中。
这样经过封装后,会将IP包交由下一层链路层,再经由网卡发送出去。(客户端机器与网关之间还有物理层的线路连接)。
:::warning
MAC地址是唯一的,从网卡正式使用开始就具有全球唯一性。MAC地址相当于身份证,IP地址是动态分配的,有可能会重复。
:::
网关会根据路由表,判断目标IP怎么走,经过多个网关的跳转最终找到目标服务器的网关,最终通过APR协议和目标IP取得目标机器的MAC地址,网络包最终可以根据MAC地址到达目的地。
服务端接收请求
服务端和客户端的流程正好相反,服务端是自下而上的。目标服务器接收到请求包后,会取下请求中的MAC头交由网络层中发现IP也对上了,就会取下IP头交由传输层,传输层会原路返回包,告诉客户端请求接收到了。如果过了一段时间(超时时间),客户端还是没有收到来自服务器的回复,会重新发送这个包,直到收到回复为止。同样,这个重发也不是重新发起上面那个客户端请求,而是传输层将同一个请求反复重试,对用户来说,只有一次请求。回到目标服务器,当网络包到达传输层后,TCP头中有一个服务器监听端口号,通过这个端口号,可以找到 服务端正在监听的端口,即 Nginx 中配置的 443 端口,端口对上之后,取下 TCP 头,将网络包交给应用层,开始对 HTTP/HTTPS 请求进行处理。如果是前端资源的话,直接通过 Nginx 进行响应,如果是 PHP 动态请求的话,再由 Nginx 将请求转发给后台运行的 PHP-FPM 进程进行处理。当然如果 Nginx 做了负载均衡,以及后端服务是分布式系统或者提供了微服务的化(涉及到RPC远程调用),还有更加复杂的处理逻辑,这些我们放到后面去讲。当后台服务处理完成后,就会返回一个 HTTPS 的响应包,告知用户请求成功,并返回响应内容,同样这个网络响应包和请求包一样,自上而下经过层层打包,顺着来路经过层层「关卡」(网关),回到发起请求的客户端,然后再经过自下而上的处理,最终在客户端浏览器显示。