五层协议
层级 | 协议 | 协议 | 协议 | 协议 | 协议 | 协议 | 协议 | 协议 |
---|---|---|---|---|---|---|---|---|
应用层 | DHCP | HTTP | HTTPS | RTMP | P2P | DNS | GTP | RPC |
传输层 | UDP | TCP | ||||||
网络层 | ICMP | IP | OSPF | BGP | IPSec | GRE | ||
链路层 | ARP | VLAN | STP | |||||
物理层 | 网络跳线 |
一次网络请求的完整周期
从客户端发起请求,网络数据是从上而下的
应用层
以 Laravel 学院为例,要访问这个网站,首先需要在浏览器中输入 laravelacademy.org,这只是网站的域名,浏览器并不知道要去哪里访问对应的资源,这个时候就需要用到DNS协议对域名进行解析,在域名注册商(如阿里云旗下的万网)那里绑定了域名与对应的服务器IP地址,所以DNS就可以通过域名获取到与之绑定的 IP 地址,比如114.215.241.29,IP地址相当于互联网世界的「门牌号」。
知道了目标 IP 地址后,浏览器就开始打包本次请求,这里根据传输数据加密与否分为 HTTP 请求和 HTTPS 请求,使用的分别是 HTTP 协议和 HTTPS 协议,无论使用哪种协议,都要封装请求头和请求参数,以便服务器返回相应的响应:
报文 | 格式 |
---|---|
HTTP头 | GET、URL、HTTP1.1正文格式、正文长度 |
- | 请求数据 |
DNS、HTTP、HTTPS 所在的层是应用层,经过应用层封装后,浏览器将应用层的包交个下一层去完成,这个过程通过 socket 编程来实现。
传输层
下一层是传输层,传输层有两种协议,一种是无连接的 UDP 协议,一种是面向连接的 TCP 协议,UDP 无需建立连接即可通信,但是不可靠,可能会丢包,TCP 需要三次握手建立连接,能够保证数据包达到目的地,但是有额外的开销,性能和速度不如 UDP。具体使用哪个协议,需要根据具体需求来定。
对于 HTTP/HTTPS 请求来说,都是基于 TCP 协议的可靠连接,TCP 协议有两个端口,一个是浏览器监听的端口(监听服务器响应),一个是服务器监听的端口(监听客户端请求,对于 HTTP 请求,通常是 80 端口,对于 HTTPS 请求,通常是 443 端口)。操作系统会根据端口来判断,将得到的包转发给哪个进程:
报文 | 格式 |
---|---|
TCP头 | 浏览器端口:12345服务器端口443 |
HTTP头 | GET、URL、HTTP1.1正文格式、正文长度 |
- | 请求数据 |
网络层
传输层封装完成后,浏览器将包交给操作系统的网络层,网络层的协议是 IP 协议,在这一层,会给传输层传递过来的包加上 IP 头,其中包含源 IP 地址(浏览器所在机器)、目标 IP 地址(服务器所在机器)等信息:
报文 | 格式 |
---|---|
IP头 | 客户端IP:192.168.0.1服务器IP:114.215.241.29 |
TCP头 | 浏览器端口:12345服务器端口443 |
HTTP头 | GET、URL、HTTP1.1正文格式、正文长度 |
- | 请求数据 |
操作系统知道目标机器 IP 地址后,就开始根据它来寻找目标机器,如果是本机局域网内的机器,可以直接通过 IP 地址判断出来,如果是局域网之外的机器,则需要通过网关去外面的世界查找。显然,这里的目标 IP 不在本地局域网。
链路层
操作系统启动的时候,就会通过 DHCP 协议配置 IP 地址,以及默认网关的 IP 地址:192.168.1.1。操作系统会通过 ARP 协议通过 IP 地址获取网关的 MAC 地址,并将本地网关和计算机的 MAC 地址添加到 MAC 头中:
报文 | 格式 |
---|---|
MAC头 | 本地客户端MAC地址本地网关MAC地址 |
IP头 | 客户端IP:192.168.0.1服务器IP:114.215.241.29 |
TCP头 | 浏览器端口:12345服务器端口443 |
HTTP头 | GET、URL、HTTP1.1正文格式、正文长度 |
- | 请求数据 |
这样,操作系统就将 IP 包交给了下一层 —— 链路层,再经由网卡发送出去(客户端机器与网关之间还有物理层的线路连接)。
注:使用网卡(NIC)的情况下,MAC地址会被烧到ROM中,任何一张网卡的MAC地址都是全球唯一的。有人可能会问,有了IP地址为什么还要MAC地址?MAC地址就相当于你的身份证号,一旦出生就写死了,一辈子都不会变,而且具有全局唯一性。IP地址可以动态分配,不能保证全局唯一,只能保证局域网内唯一,相当于你的居住地址,可能过段时间就会变。 网关收到包以后,会根据自己的知识判断下一步怎么走,网关往往是一个路由器,到某个目标 IP 地址怎么走,有一个路由表。网络请求包往往需要经过多个网关的跳转,才能达到最终的目标机器。
假设网络包经过多个网关之后,最终到达了目标服务器所在的网关,通过 ARP 协议,目标服务器根据目标 IP 地址返回一个 MAC 地址,表示目标服务器在此,然后网络包通过这个 MAC 地址在服务器所在局域网内找到目标机器。
服务端接收请求的时候,与客户端发送请求相反,网络流是自下而上的
目标服务器发现与网络请求包的 MAC 地址对上了,取下MAC头,将包传递给上一层网络层,发现 IP 也对上了,就取下 IP 头,然后交给传输层。
在传输层里,对于收到的每一个包,都要回复包收到了,这个回复不是此次请求的响应,仅仅是回复包已收到而已,这个回复会沿着包的来路回去。如果过了一段时间(超时时间),客户端还是没有收到来自服务器的回复,会重新发送这个包,直到收到回复为止。同样,这个重发也不是重新发起上面那个客户端请求,而是传输层将同一个请求反复重试,对用户来说,只有一次请求。
回到目标服务器,当网络包到达传输层后,TCP头中有一个服务器监听端口号,通过这个端口号,可以找到 Laravel 学院网站正在监听的端口,即 Nginx 中配置的 443 端口,端口对上之后,取下 TCP 头,将网络包交给应用层,开始对 HTTP/HTTPS 请求进行处理。
如果是前端资源的话,直接通过 Nginx 进行响应,如果是 PHP 动态请求的话,再由 Nginx 将请求转发给后台运行的 PHP-FPM 进程进行处理。当然如果 Nginx 做了负载均衡,以及后端服务是分布式系统或者提供了微服务的化(涉及到RPC远程调用),还有更加复杂的处理逻辑,这些我们放到后面去讲。
当后台服务处理完成后,就会返回一个 HTTPS 的响应包,告知用户请求成功,并返回响应内容,同样这个网络响应包和请求包一样,自上而下经过层层打包,顺着来路经过层层「关卡」(网关),回到发起请求的客户端,然后再经过自下而上的处理,最终在客户端浏览器显示 Laravel 学院首页。
好了,通过了解一次网络请求的完整生命周期,你应该对网络包流转过程中网络分层和使用到的协议,乃至 Web 请求和响应的全貌有了一个更加清晰的认知。
原文来自Laravel学院君