计算机网络协议基础
这里的网络协议主要围绕 Web 应用展开,主要讲述的是 TCP/IP 协议簇,如 IP、TCP、UDP、HTTP、DNS 协议等,在讲述 TCP/IP 协议之前,我们先简单概述下计算机网络的发展历史及 OSI 参考模型。
计算机网络的发展经历了单机到联机、局域网到广域网、私有网路到互联网的阶段。
在上个世纪四五十年代,那个时代的计算机都是庞然大物,计算机运行的程序和数据都需要提前装入磁带或卡带,并按照一定的顺序读取,使用户数据和程序批量,此时的计算机网络处于蛮荒时代,称之为批处理时代。
进入到六十年代,为了解决多个用户同时使用计算机的需求,可以将多个终端与一个计算机连接,从而让多个用户共享这台计算机,每个终端与计算机构成星型结构,计算机网络的概念开始浮出水面,称之为分时系统时代。
随着计算机体积日趋缩小,价格也逐步降低,使得普通公司和个人使用计算机成为可能,因而,在七十年代,计算机之间的通信技术也提上日程,计算机网络的发展进入一个崭新的时代。
最终在二十世纪八十年代,计算机网络诞生,让各种计算机互联成为可能。
而进入九十年代,伴随着「一人一机」成为可能,以及万维网、邮箱技术等全新的信息传播方式的蓬勃发展,连接各种计算机的互联网技术都以快速普及。
直到今天,互联网技术俨然已经成为国家社会的重要基础设施,不仅是计算机,手机、家用电器、穿戴式设备都可以接入到互联网中。
那么问题来了,我们知道,人与人之间的通信靠的是语言,那计算机之间的通信靠的是什么呢?答案是网络协议,不同的计算机之间需要通过遵循相同的网络协议才能进行通信,就好比两个人之间通过相同的语言才能正常交流,否则一个说中文,一个说英文就无法沟通了。
网络协议就是计算机之间通过网络实现通信时事先达成的一种「约定」,这种「约定」使不同厂商的设备、不同的 CPU 以及不同的操作系统组成的计算机之间,只要遵循协议就可以相互通信。反之,如果协议不同,就无法通信。
这个协议通常由国际标准组织来制定,比如最常见的,也是我们本系列分享重点讨论的 TCP/IP 协议,就是由 IETF 讨论制定的、互联网通信的业界标准:
需要注意的是,虽然叫 TCP/IP 协议,并不意味着这个协议中只包含这两种协议,它其实泛指的是互联网相关的协议簇,所以也可以称作 TCP/IP 网络协议族。
一次网络请求的完整生命周期
我们通过介绍一次网络请求的完整生命周期来看看在计算机网络世界中到底使用了哪些协议。
为了方便理解,我们还是对照上一篇提供的 TCP/IP 分层和协议图来看.
客户端发起请求
从客户端发起请求的时候,网络数据流是从上而下的:
以 Laravel 学院为例,要访问这个网站,首先需要在浏览器中输入 https://laravelacademy.org ,这只是网站的域名,浏览器并不知道要去哪里访问对应的资源,这个时候就需要用到 DNS 协议对域名进行解析,在域名注册商(如阿里云旗下的万网)那里绑定了域名与对应的服务器IP地址,所以 DNS 就可以通过域名获取到与之绑定的 IP 地址,比如 114.215.241.29,IP 地址相当于互联网世界的「门牌号」。
知道了目标 IP 地址后,浏览器就开始打包本次请求,这里根据传输数据加密与否分为 HTTP 请求和 HTTPS 请求,使用的分别是 HTTP 协议和 HTTPS 协议,无论使用哪种协议,都要封装请求头和请求参数,以便服务器返回相应的响应:
DNS、HTTP、HTTPS 所在的层是应用层,经过应用层封装后,浏览器将应用层的包交个下一层去完成,这个过程通过 Socket 编程来实现。
下一层是传输层,传输层有两种协议,一种是无连接的 UDP 协议,一种是面向连接的 TCP 协议,UDP 无需建立连接即可通信,但是不可靠,可能会丢包,TCP 需要三次握手建立连接,能够保证数据包达到目的地,但是有额外的开销,性能和速度不如 UDP。具体使用哪个协议,需要根据具体需求来定。
对于 HTTP/HTTPS 请求来说,都是基于 TCP 协议的可靠连接,TCP 协议有两个端口,一个是浏览器监听的端口(监听服务器响应),一个是服务器监听的端口(监听客户端请求,对于 HTTP 请求,通常是 80 端口,对于 HTTPS 请求,通常是 443 端口)。操作系统会根据端口来判断,将得到的包转发给哪个进程:
传输层封装完成后,浏览器将包交给操作系统的网络层,网络层的协议是 IP 协议,在这一层,会给传输层传递过来的包加上 IP 头,其中包含源 IP 地址(浏览器所在机器)、目标 IP 地址(服务器所在机器)等信息:
操作系统知道目标机器 IP 地址后,就开始根据它来寻找目标机器,如果是本机局域网内的机器,可以直接通过 IP 地址判断出来,如果是局域网之外的机器,则需要通过网关去外面的世界查找。显然,这里的目标 IP 不在本地局域网。
操作系统启动的时候,就会通过 DHCP 协议配置 IP 地址,以及默认网关的 IP 地址:192.168.1.1。操作系统会通过 ARP 协议通过 IP 地址获取网关的 MAC 地址,并将本地网关和计算机的 MAC 地址添加到 MAC 头中:
这样,操作系统就将 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 请求和响应的全貌有了一个更加清晰的认知,接下来,我们将各个击破,带你深入了解各个分层和协议的更多细节。