网络分层模型中比较常见的是TCP/IP 四层模型OSI 七层模型,我们先介绍TCP/IP 四层模型,再用比较的方式介绍OSI 七层模型,至于其它的5层模型和3层模型等只作简单的说明。

1 TCP/IP 四层模型

TCP/IP这个名词指的是TCP/IP协议族(TCP/IP protocol suite),也称做Internet protocol suite,它是一组协议的统称,而不是单指TCPIP这两个协议,关于这个协议族的更多内容可以参考wiki:Internet protocol suite(https://en.wikipedia.org/wiki/Internet_protocol_suite)。

TCP/IP的四层模型从上往下(从应用程序往底层)分别是:应用层(application)、传输层(transport)、网络层(network)、链路层(link)。

当我们要把数据从网络的一端传到另一端时,数据先在发送端从上往下传递,每一层都会在上一层传递的基础上添加当前层的头部信息(封装),而接收端则从下往上分析数据,进行相应的处理。下图可以表示一个简单的模型(TCP传输):

“网络分层模型示意图”

我们来看一下每一层的作用以及相应的头部内容

链路层

以太网头部包含了两个6字节(48bit)的硬件地址,以及其它一些比如数据帧(frame)中传输的数据类型等(具体取决于封装格式是rfc894定义的ethernet还是rfc1042定义的ieee802)。
硬件地址就是网卡的mac地址,这个48bit的地址就是我们连接到网络的"身份证",但并不是仅靠这个地址就可以在互联网畅行无阻,假设全世界的设备都有独一无二的MAC地址,并且相互之间靠这个地址通信,那么光是缓存这些地址就要248bit=32TB,这是不现实的,所以互联网需要引入IP地址和子网来解决这个问题,而硬件地址就在一个子网内工作。

链路层主要的作用有:

  1. 发送和接收IP数据包
  2. 发送和响应ARP请求以及RARP请求,因为IP层使用的IP地址不能用在链路层用来传递数据,必须先把IP地址对应的物理地址,然后链路层根据物理地址发送数据,ARP协议就是解决IP地址到物理地址的映射

网络层

IP头部包含了两个4字节(32bit)的IP地址,以及IP头部检验和、IP协议版本、IP数据报传输的数据类型等信息,IPv4的头部是20字节(不包含可选信息)。

网络层是用来解决网络两端的设备通信的问题,引入了IP地址的概念。理论上,两台设备只要实现了链路层和网络层,那么就具备了在互联网中相互通信的条件。

当一个IP数据包从一个IP地址发送到互联网中的另一个IP地址时,基本的步骤如下:

  1. 网络层根据IP头部中的目的地IP地址查找路由表,找到对应的下一跳IP,这个地址通常不是IP头部中的目的地址,而是一个中间路由的地址
  2. 把IP数据包传给链路层,同时在调用时链路层方法时用参数传递下一跳IP,注意数据包中的目的地址没有变化
  3. 链路层根据IP地址找到对应的物理地址,然后发送出去
  4. 接收端收到报文后,查看IP头部的地址,如果发现不是发给自己的,则重复步骤1,继续发给下一眺
  5. 经历几跳直到数据到达目的IP地址,如果不能到达,则数据被丢弃

网络层的传输是无状态的,也就是说发送方只管发送,而接收方只管接收,至于数据是否送达、已经发过什么数据、哪个先发送哪个先到达等,都没有保障。想要让数据传输更可靠,只能依赖上层的传输层或者应用层来实现。

网络层涉及的协议有IP协议,ICMP协议,IGMP协议,后面两个跟传输层的TCP和UDP一样,都是放在IP包内发送的,但是从作用上来说更偏向于网络层。

传输层

TCP和UDP都是传输层的协议,以TCP举例,TCP头部包含了两个2字节(16bit)的端口号以及其它一些信息,比如滑动窗口大小等,TCP头部一般也是20字节(不包含可选项)。

TCP虽然是通过无状态的网络层发送的,但是可以通过头部信息使得通信的两端建立起一个可靠的连接。比如,TCP头部中有一个"序号"字段,给发送的数据编号,那么接收端就可以根据这个序号来判断数据是否有丢失,以及利用这个序号来让乱序到达的数据重新排序。

UDP则是不可靠的,使用UDP时则要在应用层来保证传输的可靠证。

应用层

应用层的协议就比较多样化,表现形式也不一样,大部分不常见的协议都是在应用层实现的,而且跟网络传输关系不大,所以略过。

头部信息是哪里来的

前面的图中,每一层都要添加头部,比如传输层到网络层时添加了IP头部,那么IP头部中的IP地址是哪里来的的?这可能跟不同的协议栈实现有关,但大部分都是把IP地址、端口号等信息作为参数传递的,比如linux内核的协议栈实现,在调用方法的时候都传入一个sock*指针,sock里面就包含了IP地址等一系列的参数,所以在应用层调用时就已经确定了IP地址和端口号等信息,只是分层模型在不同的层把它们封装起来。当然,网络层到链路层的转化不是这样,路由表和ARP协议的IP地址到物理地址的转化都是由相应的层处理的。

分层的好处

跟程序设计类似,分层的好处就是简化问题,让协议实现起来更方便、更灵活。理论上,所有的协议都可以一起处理,只要把TCP头部,IP头部这些可能的内容都包含在一个庞大的头部里,并设置额外的字段来辅助头部信息表示,比如对应偏移量是什么数据。可想而知,这么做会让头部信息非常复杂,协议栈实现中分析头部的方法也会非常多,也很难实现,最后可能不得不把整个头部分成几个步骤来处理(又回到了分层)。其实早期的网络就是没有分层的,发展到后来才提出要分层(详见wiki)。

分层后,有的设备可以选择只实现一部分层次和相应的协议。比如路由器,当我们的机器发送数据时,最终封装成以太网数据报,传到路由器,而路由器不需要知道包里传的是TCP包还是UDP包,只要知道包头部的IP地址,然后查找自己的路由表找到下一跳的IP地址,再继续传递到链路层发送出去,这里路由器就只实现了网络层和链路层。

分层模型的运作

虽然分层是概念上的,但是我们还是可以用抽象的角度描述整个分层模型(或者说协议栈)是如何运作的。

  1. 链路层让子网内的设备可以相互通信
  2. 网络层让处于不同的子网内的设备可以相互通信
  3. 传输层可以让不可靠的网络层通信变得可靠
  4. 应用层在前面3层的基础上实现多样化的通信方式

相关rfc文档:tcp/ip分层:rfc1122(链路层,网络层,传输层)、rfc1123(应用层)、rfc791(IP协议)

2 OSI 七层模型(OSI Model)

OSI 模型在分层上更详细,在设计之初目标就是提供一个强大的,可以满足未来需求的分层模型,也正是因为考虑了太多东西,导致这套模型+协议被认为实现起来太困难,也有人吐槽这是“一群没写过代码的人研究出来的东西”,现在互联网事实上的标准就是TCP/IP。

尽管 OSI 模型尽管没有被历史选择,但是它的分层模型还是会在很多地方被用来当作教学使用,OSI 模型跟TCP/IP分层模型通常用如下的方式对应:

osi模型和tcp/ip模型的对比

从图中可以看到,OSI模型主要是在链路层下面添加了一层物理层,以及把应用层细分成了3层,这些层次对应的分别是:

  • 物理层:最底层的硬件层,比如电缆、中继器这些设备就工作在这一层,在链路层数据通信的方式是数据帧(frame),而在物理层就是比特流了。TCP/IP模型没有这一层的定义。
  • 会话层:这一层管理两台设备之间建立的连接,在TCP/IP模型中是由TCP协议完成的,所以会话层并不完全对应TCP/IP的应用层
  • 表示层:主要处理数据格式的转化,加密解密等

注意:跟OSI模型对应的还有一套协议,它们都属于当时的OSI项目,这套协议跟TCP/IP的协议不通用,有的地方在讲解OSI模型时会说传输层使用的协议是TCP和UDP,这是不正确的,OSI对应传输层的协议是ISO/IEC 8073、TP0、TP1、TP2、TP3、TP4等,具体参见wiki

3 五层模型和三层模型

五层模型:TCP/IP跟OSI模型比,最明显的就是缺少了最下面的物理层,而上面的应用层则勉强可以对应至OSI的上面3层,所以有的地方就在TCP/IP 四层的模型的最下面添了一层物理层,于是有了 “TCP/IP 五层模型”。

三层模型:以前ARPANET使用的模型,三层分别是应用层、主机交互层(host-to-host)、网络接口层,它可以算是TCP/IP 四层模型的前身,正是因为意识到把网络传输和路由选路工作结合在一起的缺点,才把两者分开,形成了TCP协议和IP协议。