吴军老师在《前沿科技·吴军讲5G》这门课中提到:“第一代互联网的本质是机器与机器之间的连接,而第二代移动互联网的本质是人和人的联网。因为大家联网的目的不再是要利用其他人的设备,而是要找到对方那个人。因此从第一代互联网到第二代,计算机和手机不是本质,连接的对象从机器变成了人才是本质。”
我们每天都在用网络与家人、朋友、同事或陌生人进行沟通,但网络是怎么建立连接的,数据又是如何进行传输的?别说普通大众,像我们这样在应用上层做软件开发的程序员,可能也说不出个所以然来。而这正是网络协议的厉害之处:把所有复杂的底层通信逻辑都封装起来,让上层的使用者感觉一切都是透明的,如同它不存在一般。
了解一门技术的发展历史,知道事物发展的来龙去脉,才能知其所以然。所以,我们从“网络是如何出现的”这个问题开始梳理。
计算机网络的出现
A computer network is a set of computers sharing resources located on or provided by network nodes. The computers uses common communication protocols over digital interconnections to communicate with each other. These interconnections are made up of telecommunication network technologies, based on physically wired, optical, and wireless radio-frequency methods that may be arranged in a variety of network topologies.
The nodes of a computer network may include personal computers, servers, networking hardware, or other specialised or general-purpose hosts.
如果按笔者自己的理解给计算机网络下个定义,可以描述为:计算机网络就是利用行业内达成一致的通信协议,通过有线(如光纤电缆等)或无线(如WIFI,蓝牙,无线电波等)传输介质,将物理世界中的网络设备连接并进行信息交流的一套通信体系。
在上面维基百科对计算机网络定义的页面中,还列出了计算机网络发展的里程碑事件。笔者认为,有以下几个时间点需要了解:
- ARPANET(Advanced Research Project Agency Network:高级研究计划局网络,简称阿帕网),1967 年,拉里·罗伯茨来到高级研究计划署ARPA,着手筹建“分布式网络”。1969 年,阿帕网正式投入运行,首四个节点经已用电路连接,其速度为 50kbit/s。
- 1970 年代,文顿·瑟夫和罗伯特·卡恩设计并研发出了 TCP/IP,有四个版本:TCP v1、TCP v2、在1978年春天分成TCP v3和IP v3的版本,以及后来稳定的TCP/IP v4(目前因特网仍然使用的标准协议)。 其中,1972 年,阿帕网取得初步成功,扩展到 50 个节点;1975 年,TCP/IP 诞生。
- 1975 年至 1983 年间,多个网络之间的 TCP/IP 通信进行了测试验证,多个研究中心开发出了其他一些 TCP/IP 原型。其中,1982 年,TCP/IP 规范出炉,Unix 是最早实现 TCP/IP 协议的操作系统。
- 1970 年代后期,各种网络协议层出不穷,各个厂商之间的网络产品不兼容,对使用用户来说极其不方便。为了统一标准,国际标准化组织(ISO)出手干预,开始制定计算机网络标准。
- 1983 年 1 月 1 日,ARPANET 正式将通信协议替换为 TCP/IP。ARPANET 是因特网的前身,而 TCP/IP 是用于因特网的通信协议,是如今计算机网络世界使用最广泛的协议。TCP/IP 的启用大大提高了网络通信效率,被认为是全球互联网诞生的标志。
- 1984 年,ISO 发布了著名的 ISO/IEC 7498 标准,它定义了网络互联的 7 层框架,也就是开放式系统互联参考模型(OSI,Open System Interconnection Model)。
- 1989 年左右,TCP/IP 在局域网上的应用迅速普及。
- 1990 年代,互联网开始商用,互联网服务供应商的数量剧增。
需要说明的是,OSI 是一个参考框架,不是强制标准,因为此时像 TCP/IP 等协议已经在很多网络产品中使用了,不可能推倒重来,但它对网络协议的指导作用还是有相当影响的。另外,TCP/IP 并非 ISO 制定的某种国际标准,而是 IETF(Internet Engineering Task Force:互联网工程任务组,一个开放的民间开放标准组织) 致力推进的一种标准化作业的协议(即非官方认定,但属于业界公认的标准)。
在《图解 TCP/IP》一书中,对计算机网络的发展总结成了 7 个阶段,将其摘录到这里:
年代 | 阶段 | 说明 |
---|---|---|
1950 年代 | 批处理时代 | 先将用户程序和数据装入卡带或磁带,并由计算机按照一定的顺序读取,一次性批量处理。需要由专业人员处理,普通人一般无法使用 |
1960 年代 | 分时系统时代 | 处理器按时间片轮流执行不同的用户程序,让多个用户通过各自的终端使用同一台计算机系统,从而实现了“一人一机”的目的 |
1970 年代 | 计算机间通信时代 | 为提高工作效率,需要实现计算机间数据的交换,计算机间的通信技术开始出现 |
1980 年代 | 计算机网络时代 | 多种不同类型的计算机之间互联网络诞生 |
1990 年代 | 互联网普及时代 | E-mail、WWW等信息传播方式快速发展,使得互联网网络广泛普及 |
2000 年代 | 以互联网技术为中心的时代 | 电话网逐渐被 IP 网所取代 |
2010 年代 | 无论何时何地一切皆 TCP/IP 的网络时代 | 人们开始关注网络安全 |
不过,笔者个人觉得最后一个阶段有些不妥,叫网络融合(固定电话网络与移动通信网络的融合,互联网与通信行业的融合)或万物互联时代的到来可能会更好一些。
从整个发展历程来看,随着计算机的普及,信息交换的需求越来越大,而这背后反映的其实是人与人之间的连接越来越紧密。可以说,一部计算机网络的发展史其实就是一部人类信息传播与共享的交流史。
而在这个过程中,TCP/IP 协议栈居功至伟。
TCP/IP 协议栈
如上图所示,TCP/IP 协议总共四层,如同搭积木一样,每一层需要下一层的支撑,同时又支撑着上一层。任何一层被抽掉,都有可能导致整个协议栈无法正常运行。
Butler Lampson 有一句名言:"All problems in computer science can be solved by another level of indirection." 从 TCP/IP 协议栈这里,我们可以很直观的体会这种设计意图:通过分层,将一个复杂的事务拆解成一个个简单的小任务,从而逐个攻破。在软件设计中,这种思想也被称为解耦。
笔者将每一层的作用及相关的内容进行了梳理,如下表所示:
前面提到,TCP/IP 出来之后,ISO 为了从理论上统一套网络标准,便制定了一套 OSI(Open System Interconnection Model:开放式系统互联模型) 参考模型,下面我们就来看看这个模型的基础框架是怎样的。
OSI 参考模型
维基百科:OSI 定义了开放系统的层次结构、层次之间的相互关系以及各层所包括的可能的任务,作为一个框架来协调和组织各层所提供的服务。OSI 参考模型并没有提供一个可以实现的方法,而是描述了一些概念,用来协调进程间通信标准的制定。即 OSI 参考模型并不是一个标准,而是一个在制定标准时所使用的概念性框架。
也就是说,OSI 只是一个理论模型,并没有被具体实现过。基于前面 TCP/IP 的模型,笔者在其左边绘制了 OSI 的分层模型。
从图上看,一个很明显的感觉就是 OSI 模型划分的更细,职责更明确。同时,OSI 每一层都有对应的层次编号(L1 ~ L7),我们平时经常听说的“xxx层”概念,比如“二层转发”、“三层路由”、“四层负载均衡”和“七层负载均衡”等,这里的层次就是来自 OSI 参考模型。
同 TCP/IP 协议栈一样,笔者也将每层的相关内容总结成了一张表格:
上面也提到,分层明确了职责,但为了区分各层,需要增加相应的标识。具体的流程是这样的:发送端会从上向下在每一层中附加对应的头信息,而接收端则正好相反,从下到上逐层摘掉对应的头信息。每一层摘掉对应的信息后,会根据信息进行逻辑处理。
以一个 HTTP 请求为例(省略很多细节),发送端
- 应用层会添加 HTTP 头和 HTTP 正文;
- 到了传输层会增加 TCP 头(源端口号,目的端口号);
- 到了网络层会增加 IP 头(源 IP 地址,目的 IP 地址);
- 到了数据链路层,会增加 MAC 头(源 MAC 地址,目的 MAC 地址);
- 最后通过物理设备发送出去。
到了接收端,则正好相反:
- 二层拿到数据包,会摘掉对应头,拿出数据进行判断,如果与我的 MAC 不相符,一般会丢弃;如果是发给我的,然后会根据头中的协议类型,这里会发给三层处理;
- 三层同样摘掉对应的头(或偏移地址),拿出数据进行判断,是我的 IP 就继续处理,不是我的 IP 就转发出去;
- 到了四层,也是类似,根据头中的端口号找到监听该端口的应用程序处理;
- 到了应用层,接收对应的 HTTP 内容,然后按照应用代码逻辑进行处理,比如创建一笔订单。
参照《图解TCP/IP(第5版)》上的图,笔者绘制了一遍这个流程图:
后面的学习笔记中,笔者还会再次详细梳理这个流程。
笔者觉得,OSI 参考模型和 TCP/IP 协议栈挺有意思的:一个是理论标准,一个是事实标准。那这二者是如何对应的呢?
OSI vs TCP/IP
沿用前面的图,这里将 OSI 与 TCP/IP 进行简单的对应:
可以看到:
- OSI 七层模型更完善,职责更明确。TCP/IP 是一个实用性的纯软件栈,对物理层没有明确定义(即网卡、光纤、电缆等物理设备没有进行说明,也就是说 TCP/IP 是默认两个设备可以进行通信前提下开发出来的软件栈),而 OSI 则补上了这个缺失。
- 在有的资料中,将 OSI 的 physical layer 对应到 TCP/IP 协议栈的 aetwork access (link) layer,所以笔者画了一条虚线。
- OSI 五六七层都对应到 TCP/IP 协议栈的 application layer,这里面也是有原因的。OSI 的分层模型在四层以上分的太细,而 TCP/IP 实际应用时的会话管理、编码转换、压缩等和具体应用经常联系的很紧密,很难分开。例如,HTTP 协议就同时包含了连接管理和数据格式定义。也就是说,根据具体的应用协议(如 HTTP,FTP, TELNET,POP3等),很多 OSI 在五六七层描述的内容,统一都在应用程序中实现了。
- OSI 七层模型分的细,带来的一个劣势就是数据需要层层传递,在性能上会有所损失。
笔者再以周志明老师在《凤凰架构》的“Linux 网络虚拟化”这一小节中的网络通信模型图为例进行补充:
- 一般情况下,应用层以下(OSI 中指四层及以下)都在内核空间,而应用层则属于用户态。所以,网络数据包在传递过程中难免会因为用户态与内核态的来回切换而导致性能损失。
- 前面在梳理 TCP/IP 协议栈时,就提到相关功能由操作系统提供,便是指的内核调用。之所以要在内核态实现,主要出于数据安全隔离的考虑,防止应用程序窃听或伪造应用程序的通信内容。
- Socket:应用程序通过内核提供的 Socket 编程接口来和内核空间的网络协议栈进行通信。
- Device:这里的 Device 指的是网络访问层中面向系统一侧的接口,即面向操作系统开放的接口。其主要作用是抽象出统一的界面,让程序代码去选择或影响收发包的出入口(比如决定数据应该从哪块网卡设备发送出去)以及准备好网卡驱动工作所需的数据(比如来自上一层的 IP 数据包、通过 ARP 协议得到 Next Hop 的 MAC 地址等)。
- Driver:网卡驱动程序,是网络访问层中面向硬件一侧的接口,网卡驱动程序会通过 DMA(Direct Memory Access,直接内存访问) 将主存中的待发送的数据包复制到驱动内部的缓冲区之中。
总结
- 判断某个协议工作在第几层:一般情况下,由操作系统提供的能力都在四层及以下,而需要应用程序自己实现对应功能的基本都在七层。比如,DNS 协议,CDN 等都工作在应用层。
- 四层,七层这些概念是从 OSI 模型来的,TCP/IP 模型中对应的称呼是传输层,应用层。
- “二层转发”、“三层路由”、“四层负载均衡”和“七层负载均衡”:
- 二层转发:设备工作在数据链路层,帧经过交换机设备时,检测帧的头部信息,拿到目标 MAC 地址进行本地转发和广播。
- 三层路由:设备工作在网络层,数据包经过有路由功能的设备时,设备分析报文中的头部信息,拿到目标 IP 地址进行本地转发或选择下一个网关。
- 四层负载均衡:设备工作在传输层,基于 TCP/IP 协议的特性,利用 IP,端口等实现对后端服务器的负载均衡。
- 七层负载均衡:设备工作在应用层,比如基于 HTTP 协议的特性,解析 HTTP 报文里的 URI、主机名、资源类型等数据,再以适当的策略转发给后端服务器。
- “二层设备”、“三层设备”:区别主要是这些设备上跑的程序不同,二层设备只将 MAC 头摘下来,判断是丢弃、转发还是自己留着,而三层设备则将 MAC 头摘下来之后,再把 IP 头摘下来,看看到底是丢弃、转发还是自己留着。
- 只要网络上跑的包,都是完整的,可以有下层没上层,但绝对不会有上层没下层。对于 TCP 协议来说,三次握手也好,重试也好,只要想发出去包,就要有 IP 层和 MAC 层,否则发不出去。
参考资料
- 图解TCP/IP(第5版),by [日]竹下隆史 / [日]村山公保 / [日]荒井透 / [日]苅田幸雄
- 凤凰架构,by 周志明
- 透视HTTP协议,by 罗剑锋
- 趣谈网络协议,by 刘超