彻底弄懂 TCP/IP 协议簇 —— 概述

写在最前

大约在两年前,我曾经在网易云课堂上简单复习过一次 TPC/IP 协议簇,当时并没有特别深入,只是大概记录了一些皮毛知识,在后续两年时间至今,虽然也多多少少更深层次去了解过一些 TCP/IP 的相关细节知识,但是还是感觉并没有系统化的深入理解过,遂决定在今年精读《TCP/IP 详解卷1》(第二版),预估会花费 3 个月左右的时间(因此会持续更新),希望通过这一次精读,能对 TCP 协议有一个更上一层的理解。

ISO vs TCP/IP协议簇

我们在学习计算机网络的时候,基本都会知道 ISO 七层模型,但是在真正实现时,并没有完全遵循七层模型,它只是国际标准化组织 ISO 提供的一个标准,因为如果完全按照七层模型来实现计算机网络将过于复杂,因此各家厂商实现只是参考该标准,最终形成了我们常见的 TCP/IP 四层协议簇。

下图是 ISO 七层模型和 TCP/IP 四层协议簇的对应关系: ISO_TCPIP

关于 TCP/IP 协议簇的四层划分,也有一些看法认为要划分五层,也就是 TCP/IP 协议簇下四层与 OSI 七层模型的下四层一一对应,而把 OSI 七层模型中的上三层合并成一层,统称应用层。即: 物理层、数据链路层、网络层、传输层、应用层。

下面简单介绍一下 TCP/IP 四层每一层的做用:

  • 数据链路层:处理与传输介质(网线、光纤等)的物理接口的细节,负责从网络层向物理层发送数据帧;
  • 网络层:处理分组在网络中的活动,例如:寻址、建立连接等;
  • 传输层:为两台主机上的应用程序提供端到端的通讯,是整个模型中“承上启下”的一层;
  • 应用层:处理特定的应用程序细节,它是应用程序访问网络服务的窗口,直接面向应用程序;

从一个例子出发

从上面我们已经知道了 TCP/IP 模型的分层结构以及每一层的作用,但是这些晦涩的描述你真的能理解透彻吗?为了帮助我们对 TCP/IP 模型有一个具象化的认识,让我们从一个现实场景出发,进入到 TCP/IP 四层模型中。

假设你是公司的领导,你的办公室在整个公司大厦 X1024 号房间,现在你需要寄一份文件给你的客户,客户地址是他们公司大厦 Y21 号房间,根据文件的重要程度,客户对于丢件有不同的容忍度,例如:合同不允许丢件(TCP),普通文件则允许丢件(UDP),而文件类寄件都是由公司前台负责,选择的是邮政 EMS 快递,且邮政 EMS 有一个限制,即它的文件袋最大只能装下一张 A4 大小的纸张。

以上就是模拟出来的一个寄件场景,现在你需要寄一份三页 A4 纸的合同给客户,你把整理好的合同给前台,叮嘱前台不要丢件,前台小姐姐也是很负责认真,为了保证合同安全,不仅按照邮局的规定用三个文件袋一一封装好每一页合同,还把每一页合同的内容都复制了一份,防止寄件过程中丢失,然后前台小姐姐在每一个封装好的文件袋上填上客户的房间号 21 号,并交给了快递员,快递员收件时补充上对方的地址:“双击省老铁市666区没毛病大厦Y”,最后快递小哥把这三个快件带回到集散中心,通过陆运或者空运等方式寄送出去。

下图为 TCP/IP 模型示意图: tcpip_示意图

为什么要分层

网络上或者一些书上对于为什么网络要分层,劈里啪啦写了一大堆,其实总结成一句话就是:为了解耦

这就像我们写代码,随着需求复杂度的提升,你必须要把项目模块化来减少各个模块的耦合度,方便维护和升级。网络更是这样,而且网络是一个非常之复杂的体系结构,分层让每一层只关心自己负责的功能,各层有清晰的界限,灵活性好,易于实现和标准化,正所谓“无规矩不成方圆”。层次划分后,各层通过封装与分解来与其上下层来沟通、传递。

各层的传输单元

要对 TCP/IP 簇的各层所传输的数据单元的名词有一个了解,不仅是简单知道中文名称,更要知道其对应的英文名词,我个人感觉这是很重要的,如果概念都做不到清晰,就谈不上深入理解了。

下表是 TCP/IP 协议簇各层以及其对应的传输单元名称:

名称
应用层数据或者消息(Data/Message)
传输层UDP: 数据报(Datagram)
TCP: 数据段(Segment)
网络层分组/包(packet)
数据链路层帧(frame)
物理层PDU(bit)

封装

在分层体系结构中,相邻的层不可避免会有数据通讯,此时封装与分解就产生了。我们把自顶向下的传递称为“封装”,把自底向上的传递称为“分解”,就像快递,寄件是一个逐层包装的过程,收件是一个逐层拆包的过程。

这些通讯的数据必须要遵从每一层的特有的消息对象格式,称之为 PDU(Protocol Data Unit),当某层获得了它上层的 PDU,它不关心这个 PDU 内具体有什么信息,只是将来自上层的数据看成一个不透明的信息(类似一个黑盒数据),它只会按照它所在层的规则,在头部(也可能在尾部)附加上自己的头部,然后传递给下一层,这就是封装所做的事。例如:TCP 数据段传递给 IP 层时,IP 层再对它处理,比如 IP分片、添加 IP 头部等,由此有产生了另一个 PDU 对象,传递给链路层。

下图是一个 TCP 应用程序的封装过程: tcpip_封装

分解

下面思考一个问题:当网卡驱动收到一个数据帧,它如何知道该把数据帧内的有效载荷(即payload,是指除去了以太网数据帧的头部和尾部 CRC 校验码的数据)交给上层(即网络层)的哪个协议处理,是 IPv4 协议还是 ARP 协议呢?

解决办法其实很简单粗暴,每一层 PDU 的头部都会一个字段来记录其有效载荷的协议类型,例如:以太网数据帧的头部用一个 2个字节来标识有效荷载是 IP 包(0800)还是 ARP 包(0806)等;IP 头部用一个字节来标识有效载荷是 TCP(6) 还是 UDP(17),最后由传输层通过端口分解,最终把应用数据传递给应用程序。

下图描述了一个分解过程: tcpip_分解

总结

现代网络采用分层体系,从最底层的物理传输介质开始一直到主机上运行的应用程序,逐一分层,以此降低耦合性,使得网络框架易于开发、灵活扩展以及标准化。相邻的层之间通过封装和分解的方式向下和向上传递。

本文对 TCP/IP 协议簇体系做一个概述,在接下来的博文我会逐层进行详细的论述。