今天看啥  ›  专栏  ›  去哪儿技术沙龙

网络七层协议—从物理层到传输层的抽象

去哪儿技术沙龙  · 掘金  ·  · 2021-05-27 17:56
阅读 66

网络七层协议—从物理层到传输层的抽象

作者简介:冯志明,2019年至今负责搜索算法的相关工作,擅长处理复杂的业务系统,对底层技术有浓厚兴趣。

简述

上一篇我们讨论了 Linux 网络 I/O 的结构。

为什么有这么多的结构,或者说为什么网络 I/O 这么复杂呢?

包括一些名词,比如 MSS,IFG 是什么也没讲清楚,本篇就来把这些讲清楚。

Linux 的网络 I/O 完全是基于“网络七层协议”而设计的,内核空间包含了从物理层到传输层。所以要想搞清 Linux 网络 I/O 的结构,需要讲清楚“网络七层协议”。

本篇文章作为学习 Linux 网络 I/O 的结构及网络 I/O 中的零拷贝相关原理的储备知识,讨论的重点在于“网络七层协议”对网络 I/O 的限制以及每一层对上一层提供的抽象,而不在于讨论协议本身。

OSI 体系结构有7个层次,每个层次都完成信息交换任务中一个相对独立的部分,具有特定的功能。

1 物理层

数据在物理层的表现就是不同“介质”中的“信号”。

常见的介质包括:电线、光纤、空气、真空等。对应的信号有:电信号,光信号,电磁信号。物理层做的就是把不同介质上的信号, 抽象为0和1,作为信息在链路层的基础。

2 链路层

2.1 简介

信号是很容易受到干扰的,发送信号的设备也未必就能100%准确地发送信号。那么怎么才能保障信息的完整传递呢?

答案是:通过“帧间距”把0/1信号, 抽象为数据帧 ,通过帧校验,确保一个帧的数据是完整的。

用“以太网”举例:

前导码(7 Byte),用于时钟同步;

帧开始符(1 Byte),标识帧的开始;

数据帧(Data frame),就是数据链路层的协议数据单元;

帧间距(IFG,Interframe Gap),12 Byte,相邻两帧之间的时间断,用于时钟数据恢复。

数据帧包括三部分:帧头,数据部分,帧尾。

  • 帧头(18 Byte)包括:MAC目标地址(6 Byte),MAC源地址(6 Byte),802.1Q标签(4 Byte)以太类型(2 Byte)
  • 数据部分(46–1500 Byte)
  • 帧尾,用于校验数据部分(4 Byte)

2.2 抽象

经过链路层的抽象, 数据在链路层的表现就是 数据帧(frame);链路层提供给网络层操作的,就是数据帧中的 数据部分,称之为 报文/数据报(datagram)

2.3 MTU/PMTU

MTU:(Maximum Transmit Unit),最大传输单元,是指链接层上能承载的 报文的大小。

网络层必须遵守MTU限制,超过MTU限制的报文是无法发送的,会被抛弃。

以下是常见媒体的MTU表,以太网缺省 MTU=1500 Byte。

PMTU:(Path mtu),两台主机通信路径中的最小 MTU。

两台主机之间的 PMTU 不一定是个常数,它取决于当时所选择的路径,而且路由选择也不一定是对称的(从 A 到 B 的路由可能与从 B 到 A 的路由不同),因此,PMTU 在两个方向上不一定是一致的。

2.4 测试你的 PMTU

使用 ping 命令时发现:当 ICMP 包的大小,大于1472时,传输就会失败,并提示 MTU=1500ICMP 的头信息是8 byte,IP的头信息是20 byte,因此 MTU=1472+8+20=1500。

3 网络层(用IPv4协议举例)

3.1 简介

网际协议(英语:Internet Protocol,缩写:IP;也称互联网协议),是用于分组交换数据网络的一种协议,任务仅仅是 根据源主机和目的主机的地址来传送数据。互联网协议提供的是一种“不可靠的”数据包传输机制(也被称作“尽力而为”或“尽最大努力交付”),IP 报文的发送,每次路径可能是不同的。

3.2 IPv4头信息

IPv4数据报,头部大小可变,一个典型的 IPv4头部包含20字节。

3.3 分片

IP 协议可以支持不同的链路层,就要适应不同的 MTU,因此 IP 报文被设计成可分片的。

当设备收到 IP 报文时,分析其目的地址并决定要在哪个链路上发送它。MTU 决定了数据载荷的最大长度,如 IP 报文长度比 MTU 大,则 IP 数据包必须进行分片。每一片的长度都小于等于 MTU 减去 IP 头的长度。

分片可能是多次的。

比如一个4,300字节的数据,在 MTU 为2,500字节的链路上传输,将进行如下分片。

假设下一跳的 MTU 为1,500字节,那么每一个分片都会被再次分成两片。

3.4 重组

当一个接收者发现 IP 报文的 DF 标志为0,且分片偏移量不为0时,它便知道这个报文已被分片。接收者需要将分片的数据储存起来,当它收齐了一个报文的所有的分片,便可以将其按照正确的顺序组装起来,并交给上层协议栈。

3.5 IP分片带来的问题

  1. 分片和重组会消耗双方的 CPU 资源,并且对接收方来说,会占用大量的内存资源。
  2. 如果某个分片报文在网络传输过程中丢失,发送方必须重传所有分片报文,给网络资源带来额外的消耗。
  3. 黑客可以构造的分片报文,总是不发送最后一个分片报文,会导致接收方内存耗尽。
  4. 除第一个分片外,其他分片不包含四层协议的信息,因此防火墙不容易做控制策略。

3.6 抽象

数据在 IP 层被抽象为 报文/数据报(Datagram),而数据分组称为分片(Fragment)。IP层提供给传输层的,就是把 "逻辑上完整的数据包",通过分片突破 MTU 限制,发送给接收方。换句话说,IP 层提供给传输层的抽象是 **数据包(packet,或者叫 TCP 分段 TCP segment)**的传输能力。

4 传输层(用TCP举例)

4.1 简介

TCP 协议(传输控制协议/Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP 协议中的知识点太多,本文只提及几个关键的部分。

4.2 传输过程

  1. 应用层向 TCP 层发送数据流。
  2. TCP 层把数据流分割成适当长度的 packet/segment,IP层把 packet 发送给接收端的 TCP 层。
  3. 为了可靠传输,每个 packet 被分配了序号,接收端收到 packet 会回一个确认消息(ACK)。
  4. 如果发送端在一定时间(RTT)内未收到确认,发送端就会重传。
  5. 通过校验函数,TCP 层可以校验每个 packet 是否有错误,错误的 packet 也会重传。
  6. 因为 IP 层并不能保证 packet 的顺序到达,所以 TCP 接收端需要通过序号重组 packet。

4.3 MSS

IP 层并没有限制数据包(packet)的大小。但是基于性能和传输效率的考虑,TCP 层会基于 MTU 协商一个限制,那就是 MSS。

MSS:Maximum Segment Size ,最大分段大小(以字节为单位)。是传输层 TCP 协议范畴内的概念,用于标识 TCP 能够承载的最大应用数据段长度。是不包含 TCP Header 和 TCP Option 的 TCP 有效载荷(Payload)。

TCP 在三次握手过程中,会在 SYN 报文中使用 MSS 选项功能,协商交互双方能够接收的 MSS 值。交互双方会以双方通告的 MSS 值中取最小值作为发送报文的 MSS。因为 PMTU 在两个方向上不一定是一致的,MSS 也可能是不一致的。

大的 MSS,确实可以节省 TCP 的头信息,增加传输效率。

大的 MSS 同时会造成 IP 分片,降低 IP 层的传输效率。上面网络层举的例子,如果我们控制每个数据包的大小都小于1,480字节,那么用3个 IP 报文就可以完成4,300字节的数据的传输。

所以推荐的 MSS = MTU - IP头 - TCP头。常见的基于以太网的协商结果:MSS=1500 - 20(IP头) - 20(TCP头) = 1460 byte。

4.4 流量控制

因为接收方需要重组 packet,并且 TCP 是面向 Stream 的,所以 TCP 重组比网络层的重组占用的内存还要大。

流量控制用来避免发送数据发送得过快而导致接收方来不及收下,所以由接收方通告给发送方进行调控。

TCP 使用滑动窗口协议实现流量控制。接收方在“接收窗口”域(接收缓冲剩余)指出还可接收的字节数量。发送方在没有新的确认包的情况下至多发送“接收窗口”允许的字节数量。接收方可修改“接收窗口”的值。

之所以叫滑动窗口,是因为根据接收窗口的大小,ack 的最大 packet 的序号,和 MSS,就可以确定可以发送的 packet 范围,这个范围是滑动变化的。并且发送顺序没有严格的要求。

4.5 拥塞控制

早期的 TCP 实现是没有拥塞窗口的。如果传输路径没有问题,定义好滑动窗口就可以控制好传输。如果传输路径有问题,比如带宽有限,承受不了这么多数据,那就会走到 TCP 的确认重传机制,这会进一步降低网络的负载能力。

所以 TCP 才提出了拥塞控制(拥塞窗口)。它一个应用就是 slow start。简单讲,发送方开始只发一小段数据,当收到了 ACK之后,再增加每次发送的数据,直到达到接收方的处理能力上限或者传输路径的负载能力上限。发送方每次发送的数据长度,就是拥塞窗口的大小。

4.6 抽象

数据在TCP层被抽象为 数据包(packet,或者叫 TCP 分段 TCP segment)

TCP 层提供给应用层的抽象称之为 流(Stream),操作系统将 TCP 连接 抽象套接字(socket),作为编程接口给程序使用。




原文地址:访问原文地址
快照地址: 访问文章快照