万字长文带你深入理解 TCP 和 UDP 的区别 😋😋😋

文章开始之前分享两个开源项目,会一直维护的,欢迎 star,如果你感兴趣或者想参与学习,可以加我微信 yunmz777,最近也在找工作 ing,欢迎内推......

浪费你两秒钟时间,我们正文开始!!!

传输层是 OSI 模型中的第四层,它在网络层(第三层)之上,并为应用层(第五层至第七层)提供服务。传输层的主要职责是提供端到端的数据传输服务,并确保这些服务是可靠的。传输层管理的是两个端系统间的数据传输,不涉及路由,那是网络层的服务。这一层的功能对于整个网络的性能至关重要,因为它控制着设局流的速度和质量。

主要功能

  1. 分段和重组:传输层接收来自应用层的数据,并将其分割成更小的单元,通常被称为段(在 TCP 协议中)或数据报(在 UDP 协议中)。这些段在目的地会被重新组合。

  2. 端到端连接:传输层在两个终端之间提供逻辑通信,而网络层则提供节点到节点的通信。

  3. 流量控制:通过控制数据包的发送速率,传输层可以防止网络拥塞。这对于避免发送方快速发送数据而接收方来不及处理的情况尤为重要。

  4. 错误检测和修正:传输层检测传输过程中的错误,并确保这些错误得到修正。这通常通过校验和、序列号以及确认应答等机制来实现。

  5. 可靠的消息传输:传输层确保数据完整无误地从源端传输到目的端。在 TCP 协议中,通过使用序列号、确认应答、重传机制等方式,提供了可靠的传输服务。

关键协议

传输层的两个主要协议是 TCP(传输控制协议)和 UDP(用户数据报协议):

TCP(Transmission Control Protocol)

TCP 的主要特点是提供可靠的、有序的和基于字节流的传输服务。它通过一个复杂的机制,包括序列号、确认响应、重传策略、流量控制和拥塞控制等来保证数据的完整性和可靠性。接下来,我们将从 TCP 的工作原理、连接管理、数据传输和控制机制等方面进行详细的解释。

面向连接

TCP 被称为是面向连接的,这是因为在一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先相互 握手,即它们必须相互发送某些预备报文段,以建立确保数据传输的参数。

TCP 连接提供的是全双工服务,如果一台主机上的进程 A 与另一台主机上的进程 B 存在一条 TCP 连接,那么应用层数据就可以从进程 B 流向进程 A 的同时,也从进程 A 流向进程 B,TCP 的链接也中是点对点的,即在单个发送方与单个接收方之间的连接。

在任何数据传输之前,必须在两端建立一个 TCP 连接。这个过程通常称为 三次握手,三次握手是建立 TCP 连接的过程,它的目的是同步连接双方的序列号和确认号,并交换 TCP 窗口大小信息。以下是三次握手的具体步骤:

  1. 第一次握手:客户端选择一个初始序列号(ISN)并向服务器发送一个 SYN(Synchronization 同步序列编号)包。这个包里不包含数据,仅仅是为了初始化序列号。例如,客户端发送一个 SYN 包,其序列号为 X。

  2. 第二次握手:服务器接收到客户端的 SYN 包后,会发送一个 SYN-ACK 包作为应答。这个包中的 ACK 号设为 X+1,表示服务器已经接收到客户端的 SYN 包,并期待收到下一个字节 X+1。同时,服务器也选择自己的初始序列号,假设为 Y,并将这个序列号放在 SYN 包中发送给客户端。

  3. 第三次握手:客户端收到服务器的 SYN-ACK 包后,会发送一个 ACK 包。这个包的序列号设置为 X+1,确认号为 Y+1,表示客户端已经接收到服务器的 SYN 包,并且准备好接收服务器的下一个字节 Y+1。

通过以上三次握手,TCP 连接建立完成,数据传输可以开始。如下是 TCP 三次握手流程图:

ini 复制代码
客户端(Client)                             服务器(Server)
   |                                           |
   |              SYN, Seq=X                  |
   |----------------------------------------->|
   |                                           |
   |             SYN-ACK, Seq=Y, Ack=X+1      |
   |<-----------------------------------------|
   |                                           |
   |              ACK, Seq=X+1, Ack=Y+1       |
   |----------------------------------------->|
   |                                           |

在上面的流程图中,有几个字段有如下解释:

  1. SYN: 同步序列编号,开始一个新连接。

  2. ACK: 确认接收,回应之前的包。

  3. Seq: 序列号,指当前数据包的序列。

  4. Ack: 确认号,确认收到的数据。

单号数据传输完成后,使用四次会搜来终止连接:

  1. 第一次挥手:当客户端完成数据发送后,它需要发送一个 FIN 包给服务器,表示客户端已经没有数据发送了,请求释放连接。假设此时客户端的序列号为 Z。

  2. 第二次挥手:服务器收到客户端的 FIN 包后,发送一个 ACK 包作为回应,确认号为 Z+1。此时服务器的接收通道关闭,但发送通道还未关闭。

  3. 第三次挥手:服务器如果也没有数据要发送,它会发送一个 FIN 包给客户端,请求释放服务器到客户端的连接。假设此时服务器的序列号为 W。

  4. 第四次挥手:客户端接收到服务器的 FIN 包后,会发送一个 ACK 包作为回应,确认号为 W+1。此时客户端的发送通道也关闭。

在四次挥手后,TCP 连接完全释放。需要注意的是,TCP 连接是全双工的,这意味着每个方向必须单独进行关闭。这是为什么需要四次挥手来结束连接的原因。最后,等待一段时间后才能彻底关闭连接,以确保最后一个 ACK 的可靠性。

ini 复制代码
客户端(Client)                             服务器(Server)
   |                                           |
   |              FIN, Seq=Z                  |
   |----------------------------------------->|
   |               ACK, Ack=Z+1               |
   |<-----------------------------------------|
   |                                           |
   |              FIN, Seq=W                  |
   |<-----------------------------------------|
   |              ACK, Ack=W+1                |
   |----------------------------------------->|
   |                                           |

TCP 三次握手主要用于在数据传输开始之前确保两个通信端点------客户端和服务器------能够建立一个稳定和可靠的连接,它通过三步验证过程保障双方的发送和接收能力均正常,并排除因旧连接请求可能引起的干扰,确保双方都准备好进行数据交换。这种机制是网络通信中保证数据准确传输的关键步骤。

如果只有两次握手,则可能有以下情况发生:一个客户端发送了一个连接请求(SYN 包)但因某种原因这个包延迟到达,这时客户端重新启动并再次发送了新的连接请求。服务器收到这个旧的连接请求后,如果没有第三次握手,就直接进入连接状态,而客户端实际上是期望与服务器建立新的连接的。

TCP 以段为单位发送数据

TCP 通过将数据打包成称为段(Segment)的单位来发送信息。每个 TCP 段包含一个首部和一个数据部分。

在 TCP 连接的建立过程中,最大消息长度(MSS, Maximum Segment Size)的确定是一个关键步骤,它确保数据包在 IP 层传输时不需要分片,从而优化网络效率。MSS 是在 TCP 三次握手阶段通过两端主机协商得出的。

MSS 的计算和协商过程
  1. 连接初始化:当两端主机准备建立 TCP 连接时,各自会在发送的 SYN 包的 TCP 首部中包含一个 MSS 选项。这个 MSS 选项指明了该主机的 TCP/IP 栈可以接受的最大数据段大小。

  2. MSS 选项交换:在三次握手过程中,客户端和服务器互相交换 MSS 值。第一次握手中,客户端向服务器发送 SYN 包,并在 MSS 选项中声明其接收数据段的最大长度。随后,服务器在响应的 SYN-ACK 包中也包含一个 MSS 选项,声明其自身的最大接收长度。

  3. MSS 的选择:一旦双方都接收到对方的 MSS 值,它们各自会选择一个最小的 MSS 值作为通信过程中的实际 MSS,以此确保所有发送的 TCP 段都不会超过这个大小,从而避免在网络中的 IP 分片。

IP 分片是什么

IP 分片(IP Fragmentation)是网络层面上处理大数据包的一种机制。当一个数据包的大小超过了网络中某一段的最大传输单元(MTU, Maximum Transmission Unit)时,该数据包需要被分割成更小的片段以便通过网络传输。

  1. 最大传输单元(MTU):这是网络上任何给定链路可以承载的最大数据包的物理限制大小。不同类型的网络有不同的 MTU 值,例如,以太网的标准 MTU 是 1500 字节。

  2. IP 分片:当一个 IP 数据包的大小超过了沿途网络的 MTU 时,它将被分割成多个较小的片段。这些片段在到达目的地后会被重新组合成原始的完整数据包。

接下来我们来了解一下分片的过程:

  1. 分片触发:当源主机发送的 IP 数据包大小超过沿途网络的 MTU 时,路由器将对数据包进行分片。源主机也可能在本地对数据包进行分片,如果它知道路径中最小的 MTU。

  2. 分片操作:

    • 每个片段都会保留原 IP 数据包的首部(稍作修改以表示这是一个片段),并包含原数据的一个连续部分。

    • 片段的 IP 头部包含一些特殊的字段,如更多片段(MF)标志和片偏移(Fragment Offset),用于帮助接收端正确重组原始数据包。

    • 更多片段标志用于指示是否还有后续的片段。

    • 片偏移字段表示该片段在原始数据包中的相对位置。

  3. 重组:重组:接收端收到所有片段后,利用片段中的偏移和序列信息将它们重组为原始数据包。如果任何片段丢失,重组将无法完成,整个数据包需要重新发送。

虽然 IP 分片使得大数据包能在各种网络环境中传输,但它带来了几个问题:

  1. 效率降低:分片和重组过程消耗额外的 CPU 资源和缓冲区空间。

  2. 可靠性问题:如果任何一个片段丢失,整个原始数据包都需要重新发送,这增加了重传的概率,降低了网络效率。

  3. 安全风险:分片可能被网络中间设备错误处理,或被用于网络攻击(如碎片重叠攻击)。

因此,在设计和维护网络及应用时,通常尽量避免 IP 分片,比如通过调整数据包大小或采用路径 MTU 发现(PMTUD)技术来适配最小 MTU,从而优化网络性能和安全性。

为什么说 MSS 能减少 IP 分片

MSS(最大段大小)的设定对于减少 IP 分片具有关键作用,主要是因为它确保 TCP 层发送的数据包大小不会超过网络路径中的最大传输单元(MTU),从而避免在 IP 层发生分片。

MSS 是 TCP 协议中定义的最大数据段大小,它指的是 TCP 数据段(Segment)的数据部分(不包含 TCP 头部)的最大长度。而 MTU 是包含了整个 IP 数据包的大小,即 IP 头部+TCP 头部+TCP 数据。通常情况下,MSS 被设置为 MTU 减去固定 IP 头部长度(20 字节)和 TCP 头部长度(通常为 20 字节),即:

ini 复制代码
MSS = MTU − IP头部长度 − TCP头部长度

其中,IP 头部长度通常为 20 字节,TCP 头部长度也通常为 20 字节,因此:

ini 复制代码
MSS = MTU − 40字节

这样设置 MSS 可以确保即使 TCP 段被封装成 IP 数据包后,整个 IP 数据包的大小也不会超过 MTU,从而避免在 IP 层进行分片。

由于 IP 分片会引入多种问题,如重组的开销、分片丢失导致的整体重传、以及安全性问题,通过控制 MSS,TCP 协议帮助降低这些风险,具体包括:

  1. 降低重传可能性:如果没有分片,那么整个 TCP 段要么完整到达,要么完整丢失,不会出现只丢失部分段的情况,这样可以减少因部分丢失导致的重传。

  2. 减少处理延迟:避免分片可以减少接收方在数据重组上的处理延迟,提高数据处理效率。

  3. 增强网络安全性:IP 分片有可能被用于执行一些网络攻击,如碎片重叠攻击等。通过避免分片,可以减少这类攻击的机会。

因此,MSS 的合理设定是网络性能优化的关键步骤之一,它通过确保每个 TCP 段的大小适应网络路径中的 MTU 限制,有效避免了 IP 分片的需要,减少了网络通信过程中的复杂性和不确定性,提高了数据传输的效率和安全性。

在 macOS 中,获取网络接口的 MTU(最大传输单元)设置可以通过命令行工具实现。这是一个快速且精确的方法,特别是对于需要详细网络配置信息的高级用户。下面是如何使用终端来查找 MTU 值的详细步骤:

首先我们查找网络服务名称,我们可以使用以下命令列出所有网络服务:

bash 复制代码
networksetup -listallnetworkservices

输出结果如下图所示:

  1. Ethernet - 这表明你的机器有一个以太网接口,它目前是启用状态。

  2. USB 10/100 LAN - 这是一个通过 USB 连接的以太网接口,也是启用状态。

  3. Thunderbolt Bridge - 这通常用于连接两台 Mac 设备,使它们可以通过 Thunderbolt 端口共享文件或网络连接,当前是启用状态。

  4. Wi-Fi - 表示无线网络接口,也是启用状态。

我们要查询 WIFI 服务的 MTU,可以使用:

bash 复制代码
networksetup -getMTU Wi-Fi

通过这些步骤,你可以轻松获取 macOS 上任何网络接口的 MTU 值。这些信息对于网络问题排查或是进行网络性能优化非常有用。

TCP 首部字段

在上面的内容中讲到 MSS 限制了报文段数据字段的最大长度,当 TCP 发送一个大文件,例如某 Web 页面上的一个图像时,TCP 通常是将该文件划分为长度为 MSS 的若干块。

如下图所示,该图展示了 TCP 首部的格式,TCP 首部相比 UDP 首部要复杂得多。另外 TCP 中没有表示包长度和数据长度的字段,可由 IP 层获知 TCP 的包长由 TCP 的包长可知数据的长度。

diff 复制代码
+-------------------------+-------------------------+
|       源端口号          |      目的端口号         |
+-------------------------+-------------------------+
|                   序列号                        |
+---------------------------------------------------+
|                 确认号                           |
+------+------------+------------------------------+
| 头长 | 保留位     |         控制位               |
+------+------------+------------------------------+
|        窗口大小         |        校验和          |
+-------------------------+-------------------------+
|          紧急指针        |       可选项          |
+-------------------------+-------------------------+
|                        数据                       |
+---------------------------------------------------+

以下是各个首部字段和载荷的详细解释:

  1. 源端口号 (16 bits): 用来识别发送端应用程序的端口。

  2. 目的端口号 (16 bits): 用来识别接收端应用程序的端口。

  3. 序列号 (32 bits): 用于确保数据传输的顺序性,对数据分片进行排序。

  4. 确认号 (32 bits): 表示接收端期望收到的下一个序列号,同时确认之前接收的数据。

  5. 头长 (4 bits): TCP 头部的长度,以 32 位字(4 字节)为单位。

  6. 保留位 (6 bits): 目前未使用,应设置为 0。

  7. 控制位 (6 bits): 包括紧急(URG)、确认(ACK)、推送(PSH)、复位(RST)、同步(SYN)、结束(FIN)等标志位。

  8. 窗口大小 (16 bits): 用于流量控制,指示发送方还可发送多少字节的数据。

  9. 校验和 (16 bits): 用于错误检测,确保数据在传输过程中的完整性。

  10. 紧急指针 (16 bits): 当紧急(URG)标志位设置时,表示这部分数据的优先级高,应立即处理。

  11. 可选项 (变长): 用于设置如最大报文段长度(MSS)等高级网络功能。

  12. 数据 (变长): 实际传输的应用数据部分。

TCP 首部的设计使得 TCP 能够提供可靠、有序且错误检测功能的数据传输服务。这些首部字段共同作用,保证 TCP 连接的高效和稳定操作。

可靠数据传输

在前面的文章中,我们已经了解到,因特网的网络层服务,即 IP 服务是不可靠的。IP 不保证数据报的成功交付,不保证数据报的顺序交付,也不保证数据报内容的完整性。具体表现在:数据报可能会因为路由器缓存溢出而永久丢失,可能会无序到达,或者数据报中的比特可能会发生损坏,例如从 0 变为 1 或反之。

由于传输层的报文段是通过 IP 数据报在网络中传输的,传输层的报文段同样会面临这些问题。针对 IP 层服务的这些不可靠因素,TCP 协议在这种"尽力而为"的服务基础上,提供了一种可靠的数据传输服务。TCP 的可靠数据传输服务确保了从一个进程到另一个进程的数据流是无损坏、无间隙、非冗余、并且顺序正确的。简而言之,通过 TCP 传输的数据流,与发送方端系统输出的字节流完全一致,从而克服了底层 IP 服务的种种限制。

超时间隔加倍

当 TCP 数据段由于超时未被确认(即未收到 ACK)时,TCP 不会立即重传该数据段,而是会等待一个超时时间间隔(Timeout Interval)。如果这个时间间隔结束还没有收到确认,TCP 就执行重传,并对超时时间间隔进行加倍,这就是所谓的 超时间隔加倍。这个过程可能会重复进行,每次超时都将时间间隔加倍,直到数据段被确认或达到一定的最大重传次数。

步骤:

  1. 初始超时设定:TCP 首次尝试发送一个数据段时,它设定一个初始超时时间间隔(RTO, Retransmission Timeout)。这个初始值通常是基于 RTT(往返时间)的估算加上一个额外的边际。

  2. 超时和重传:如果在 RTO 时间内未收到相应的 ACK 确认,TCP 将重传该数据段。

  3. 时间间隔加倍:在每次连续的超时重传后,TCP 将超时时间间隔加倍。例如,如果初始 RTO 是 1 秒,第一次超时重传后,超时时间间隔变为 2 秒,下一次超时则变为 4 秒,依此类推。

  4. 上限和恢复:超时时间间隔通常有一个上限,这是为了避免因间隔过长导致的通信延迟。当网络状况改善并成功收到 ACK 后,TCP 可以根据最近的网络条件重新计算 RTO。在多次重传失败后,如果连续的超时时间间隔达到了预设的上限,TCP 可能认为网络连接已不可靠或对端不可达,从而决定终止这一 TCP 连接。

超时间隔加倍是 TCP 以及其他网络协议中一种重要的机制,用于优化网络通信,特别是在网络条件变化大或者拥挤的环境中。这种策略的成功实施有助于提高数据传输的可靠性和效率。

快速重传

超时触发的重传是 TCP 中处理丢包的传统方法,但存在一个显著问题:如果重传计时器的设置不当(通常较长),它会导致即使只有少量数据丢失,也会引发相对较大的端到端传输延迟。这是因为发送方必须等待整个超时周期结束后才能重新发送丢失的数据包,从而增加了整体的通信时延。

为了减少这种延迟,TCP 引入了基于冗余 ACK 的快速重传机制。这种机制利用了 TCP 通信中的一个常见现象:在连续发送多个数据包的过程中,如果某个包丢失,那么该包之后接收到的所有包都会引发冗余 ACK。冗余 ACK 是指接收方针对同一个数据包发送多次确认(ACK),而这个数据包的确认已经被发送方接收过。

快速重传机制的工作原理如下:

  1. 连续数据包发送:发送方连续发送多个数据包。

  2. 数据包丢失现象:如果在这些连续的数据包中有任何一个包丢失,例如包 N 丢失,接收方在收到包 N+1 及之后的包时,将无法按顺序确认,因此它会重复发送对包 N-1(即丢失包的前一个包)的 ACK。

  3. 冗余 ACK 的接收:发送方收到多个(通常是三个)针对同一数据包的冗余 ACK,这些冗余 ACK 表明该数据包之后的某个包已经丢失。

  4. 触发快速重传:当发送方接收到三个冗余 ACK 时,它将立即重传下一个未被确认的数据包(即包 N),而不是等待重传计时器超时。

通过结合快速重传,主要有以下优点:

  1. 减少延迟:快速重传显著减少了因等待超时重传而导致的通信延迟。

  2. 提升网络响应性:通过即时响应丢包,快速重传提高了网络的整体响应性和吞吐量。

  3. 有效利用冗余 ACK:冗余 ACK 不再仅仅是重复信息,而是被用来加速丢包恢复,提高了 ACK 包的信息利用率。

通过这种优化,TCP 的性能在高速以及高丢包环境下都得到了明显的提升,减少了通信的不确定性和不稳定性,使得网络连接更加稳健和可靠。

拥塞控制

TCP 的拥塞控制策略是为了有效管理和减少网络中的拥塞状况,确保网络资源的高效利用,并避免过载。这套机制包括慢启动、拥塞避免、快速重传以及快速恢复四个主要的算法。每个算法都有其特定的功能和触发条件,它们共同协作,以动态调整数据传输速率应对不断变化的网络状况。我们将更详细地探讨这些组成部分及其相互作用。

慢启动

慢启动 的主要目的是避免在网络中引起过大的拥塞,特别是在连接开始时或者在检测到网络拥塞后。慢启动算法通过逐渐增加网络中的数据包数量来探测网络的承载能力,这个过程叫做 拥塞窗口的指数增长

当 TCP 连接开始时,TCP 使用慢启动算法初始化拥塞窗口(Congestion Window, cwnd),这是一个控制在任何时刻可放入网络中的最大数据量(以段为单位)的状态变量。

慢启动过程包括以下几个步骤:

  1. 初始化拥塞窗口:拥塞窗口 cwnd 初始化为一个很小的值,通常是 1 个最大段大小(MSS)。最初的 RFC 建议是使用 1 个 MSS,但现代实现可能使用更高的初始值,如 2 或者 3 个 MSS。

  2. 窗口增长:对于每个确认的数据段,拥塞窗口 cwnd 增加一个 MSS。这意味着每当一个数据段被确认,拥塞窗口就会增加,导致窗口每个往返时间(RTT)翻倍。因此,慢启动阶段的拥塞窗口呈指数增长。

  3. 阈值和过渡:当 cwnd 达到一个阈值 ssthresh(慢启动阈值)时,TCP 将停止使用慢启动算法。这个阈值一开始是一个较大的值(如 65535 字节),但在发生网络拥塞事件(如超时)后会进行调整。一旦 cwnd 达到 ssthresh,TCP 将转换到拥塞避免算法,拥塞窗口的增长从指数增长转变为线性增长(每个 RTT 增长 1 MSS)。

  4. 拥塞发生:如果在慢启动期间发生超时,表明网络拥塞严重,TCP 将减少 ssthresh 到当前 cwnd 的一半,并将 cwnd 重置为 1 MSS,重新开始慢启动过程。快速恢复和快速重传算法可以在某些情况下调整这些参数来更快地响应丢包事件。

慢启动帮助 TCP 避免在网络连接初始阶段就发送大量数据,这可能会超过网络的处理能力并引起广泛的数据包丢失,并通过控制数据流的速率来防止网络拥塞的发生。

拥塞避免

拥塞避免算法是 TCP 协议中用于控制数据传输速率以防止网络过载的一个重要机制。在 TCP 的拥塞控制过程中,一旦完成慢启动阶段(拥塞窗口 cwnd 达到慢启动阈值 ssthresh),就会进入拥塞避免阶段。这个阶段的主要目标是避免网络拥塞的发生,它通过调整拥塞窗口增长的速率来减少整个网络的负载。

拥塞避免算法的核心是控制拥塞窗口 cwnd 的增长速度,使其线性增加,而不是慢启动阶段的指数增长。具体过程如下:

  1. 线性增长:在拥塞避免阶段,每当收到一个确认(ACK),拥塞窗口 cwnd 不再是加倍增长。相反,它的增长会更加谨慎,每收到一个往返时间(RTT)内的所有确认,cwnd 仅增加 1 MSS(最大段大小)。这样,拥塞窗口的增长速度从指数形式变为线性形式,每个 RTT 增长约为 1 MSS。

  2. 应对丢包:如果在拥塞避免阶段发生丢包(通常通过超时或者三个重复 ACK 检测到),TCP 认为网络发生了拥塞。此时,TCP 会执行以下操作:

    • 超时:将 ssthresh 设置为当前 cwnd 的一半,然后 cwnd 重置为 1 MSS,重新进入慢启动阶段。

    • 三个重复 ACK:这通常触发快速重传机制,将 ssthresh 设置为当前 cwnd 的一半,cwnd 设置为 ssthresh 加 3 MSS,然后进入快速恢复阶段。

  3. 渐进调整:在避免拥塞的过程中,TCP 通过逐渐调整发送方的窗口大小,以寻找网络的最大承载能力而不引起拥塞。这种方法比慢启动阶段的快速增加更加稳妥,可以有效地避免网络条件突变时引起的大规模丢包事件。

通过控制数据的发送速率,拥塞避免算法帮助减少网络中的拥塞情况,避免了因为过度拥塞导致的网络性能下降甚至崩溃。减少整体的丢包率和重传次数,拥塞避免算法可以提高数据传输的效率和可靠性。

快速恢复

在前面的内容中已经讲解到,当接收方收到一个失序的数据段时(即收到的数据段不是接下来期望的数据段),它仍然会发送一个 ACK,确认它最后一次按顺序接收的数据段。如果发送方收到三个连续的重复确认(即总共四个相同的 ACK),这通常被视为网络中丢失了一个数据包的信号。

收到三个重复确认后,发送方不会等待重传计时器超时,而是立即重传那些被认为已丢失的数据段。一旦执行了快速重传,TCP 不会立刻将拥塞窗口减少到慢启动阈值的一半,而是进入一个称为快速恢复(Fast Recovery)的阶段。

快速恢复算法的目标是在不完全重启慢启动过程的情况下,通过快速调整拥塞窗口 cwnd 和慢启动阈值 ssthresh 来恢复传输效率。该算法通常在快速重传之后启动,由三个连续的重复 ACK 触发。这表示虽有一个数据包丢失,但其后的数据包已被接收方成功接收,因此需要立即重传丢包,并适当调整窗口以响应网络拥塞状态。

快速恢复的工作流程主要有以下几个步骤:

  1. 设置阈值和窗口:当发送方接收到三个重复 ACK 时,它首先将 ssthresh(慢启动阈值)设置为当前拥塞窗口 cwnd 的一半。这一半的值基于当前网络的拥塞程度估算。然后,将 cwnd 设置为新的 ssthresh 加上 3 MSS(最大段大小)。这三个 MSS 对应于接收到的三个重复 ACK,表示网络中可能还有三个段是在传输中的。

  2. 窗口增加:对于在快速恢复期间接收到的每一个后续重复 ACK,cwnd 增加 1 MSS。这样做是为了反映在快速恢复期间,每接收一个重复 ACK,网络中就可能有一个新的数据段离开网络,从而使得窗口逐渐增大。

  3. 传输新数据:在快速恢复期间,如果 cwnd 允许,发送方可以继续发送新的数据。这种策略帮助维持网络中的数据流,防止由于窗口过小而导致的网络吞吐量下降。

  4. 退出快速恢复:如果在快速恢复期间收到新的 ACK(即确认了新的数据传输),则表示网络中的数据传输已经回到正常状态。此时,发送方将 cwnd 设置为 ssthresh 的值(即快速恢复开始时设置的值),并退出快速恢复阶段,转入拥塞避免阶段。

快速恢复算法通过快速重传避免了长时间的超时等待,维持高数据发送率即使在丢包情况下也不会大幅降低网络吞吐量,并通过即时调整窗口大小应对拥塞迹象,从而优化网络响应并平滑传输性能。

拥塞控制通过以上这些机制的综合作用使得 TCP 能够适应各种网络条件,动态调整其数据传输速率,最大化效率,同时避免过度拥塞,保证网络资源的公平使用。通过这种策略,TCP 优化了数据流和整体网络响应,确保了数据传输的高效与可靠性。

流量控制

TCP 的流量控制是一个关键的机制,用于确保网络中的通信双方能够以对方能接受的速率发送数据。这是通过动态调整发送方的数据发送速率来实现的,以防止接收方的缓冲区溢出。这种机制保证了数据传输的高效性和稳定性,特别是在网络状况和负载可能快速变化的情况下。

TCP 流量控制主要依赖于 滑动窗口 协议。这个协议不仅用于流量控制,还用于实现可靠传输(如确认收到的数据,重传丢失的数据包等)。

滑动窗口是 TCP 连接中的每一方都维护的一个窗口,这个窗口决定了在等待对方确认前可以发送多少数据。窗口的大小(即窗口容量)是根据对方提供的缓冲空间大小来确定的,这个大小值通过 TCP 段中的窗口大小字段告知对方。

  1. 接收窗口(rwnd):

    • 接收窗口的大小是基于接收方的缓冲区能力调整的。

    • 接收方通过 TCP 头中的窗口大小字段告诉发送方自己还能接受多少字节的数据,即当前接收窗口的大小。

    • 这个值会根据接收方处理数据的速度动态变化。

  2. 发送窗口:

    • 发送方根据接收方的窗口大小调整自己的发送窗口。

    • 发送方只能发送接收窗口所允许的数据量,即使它的数据要多得多。

它的工作流程主要有以下步骤:

  1. 初始化:连接建立时,双方互相通告各自的窗口大小。

  2. 数据传输:

    • 发送方根据自己的发送窗口和接收方的接收窗口大小(whichever is smaller)发送数据。

    • 接收方每收到一个段后,如果正确无误地按顺序接收,它就会更新自己的接收窗口大小,并通过确认段(ACK)回传这一信息。

  3. 窗口更新:

    • 如果接收方的缓冲区被充分消费(应用程序读取了数据),它可以通过发送一个更新的窗口大小给发送方来增加窗口大小,从而允许发送方增加传输的速率。

    • 如果接收方处理数据较慢,未能及时读取缓冲区中的数据,其窗口大小将减小,从而通知发送方减缓发送速度。

流量控制通过动态调整数据流的速率来防止接收方被过量的数据淹没。这是尤其重要的,因为在网络条件或系统负载发生变化时,固定的数据发送速率可能会导致丢包、延迟增加或通信中断。

TCP 流量控制与拥塞控制的区别:

  1. 流量控制的主要关注点是保持发送方发送数据的速率不超过接收方的处理能力,目的是防止接收方的缓冲区溢出。

  2. 拥塞控制的主要关注点是网络中的拥堵情况,目的是减少整个网络中的数据包丢失事件,优化网络的整体性能。

流量控制和拥塞控制共同保证了 TCP 网络的稳定性和效率,但它们关注的焦点和实施机制不同。流量控制通过接收窗口来直接控制发送速率,而拥塞控制则是通过控制数据在网络中的流动来间接影响发送速率。

TCP 中是如何做到提高网络利用率的?

在 TCP 当中也是如此,如果发送端不停地接收发送端发送很小的包,一个本该可以一次完成的事情却被分成了上 N 次。这种频繁的发送是存在问题的,不光是传输的时延消耗,发送和确认本身也是需要耗时的,频繁的发送带来了巨大的时延。

Nagle 算法

Nagle 算法的核心思想是尽可能减少发送小的数据包,特别是在网络延迟较高的环境下。在没有收到前一个数据包的确认信息(ACK)之前,它会将输出数据缓存起来,而不是立即发送一个小数据包。

当发送应用程序生成数据时,TCP 不会立即发送一个数据包,而是等待,如果缓冲区内的数据达到网络包的最大长度(通常为 MSS,最大段大小)或者收到了之前所有数据的 ACK,它才发送数据。

发送条件主要有以下几个方面:

  1. 如果数据已经达到最大段大小(MSS),则立即发送。

  2. 如果数据量小于 MSS 但已经收到前一个数据包的 ACK,则也发送当前的数据。

  3. 如果既没有达到 MSS 也没有收到 ACK,数据会被缓存,不会立即发送。

如果之前数据没有接收到 ACK,一旦接收到之前数据的 ACK,TCP 将发送缓冲区内所有待发送的数据。

Nagle 算法的优点主要有以下几个方面:

  1. 减少网络拥塞:Nagle 算法通过合并频繁的小数据包,减少了网络中的包总数,这降低了网络的拥塞程度,提高了网络的使用效率。

  2. 提高数据传输效率:合并多个小数据包成一个大的数据包可以减少每个数据包所需的固定帧头部分的开销,从而在传输大量小消息时提高带宽利用率。

  3. 降低服务器和客户端的 CPU 负荷:处理大量小数据包需要较多的 CPU 资源进行处理(例如:分包、封包、解包等操作)。Nagle 算法通过减少数据包数量,可以降低 CPU 的处理压力。

  4. 优化长连接中的数据传送:在一些需要长时间保持连接的应用中,例如 HTTP 持久连接(HTTP Persistent Connections),Nagle 算法可以有效地减少因频繁发送小数据包而造成的性能问题。

Nagle 算法也不是没有问题,它的缺点主要有以下几个方面:

  1. 延迟增加:Nagle 算法需要等待 ACK 或积累足够的数据才发送数据,这会引入额外的延迟。特别是在交互式应用如 Telnet 或 SSH 中,用户可能会感受到明显的响应延迟。

  2. 与 TCP 延迟确认的冲突:当 Nagle 算法与 TCP 的延迟确认(Delayed ACK)功能一同使用时,可能会导致更高的延迟。这是因为发送方在等待接收方确认之前不会发送更多的数据,而接收方则延迟发送确认,试图等待更多的数据以进行确认,这样互相等待就可能形成死锁。

  3. 不适合实时应用:对于需要实时处理的应用(如游戏、实时视频会议等),Nagle 算法的延迟效果会对用户体验产生负面影响。

  4. 小批量数据交互效率低:如果应用的通信模式主要是小批量数据交互,Nagle 算法可能会反而降低通信效率,因为它需要积累足够多的数据才进行发送。

延迟确认应答

在 TCP 连接中,每个接收到的数据包通常都需要被确认。在标准的操作中,接收方收到一个数据包后,会立即发送一个确认包(ACK)回发送方。然而,这种"即时确认"方式在某些情况下可能会导致网络效率低下,因为每个数据包都需要单独确认。

延迟确认应答技术通过延迟发送确认包来优化这一过程。接收方不是在每个数据包到达时立即发送 ACK,而是等待一段短暂的时间(通常不超过 200 毫秒)。在这段延迟期内,如果接收方接收到更多的数据包,它可以在一个确认中同时确认多个数据包,或者如果接收方需要发送数据到发送方,它可以将确认信息附加在响应数据中,这样可以将确认和数据一起发送。

延迟确认的优点主要有以下几个方面:

  1. 减少网络流量:通过减少发送的 ACK 包的数量,延迟确认可以显著减少网络上的总流量,特别是在数据包小或交互密集的应用中。

  2. 提高数据吞吐量:在某些情况下,合并 ACK 可以减少网络拥堵和数据包冲突,从而提高整体数据吞吐量。

  3. 优化带宽利用率:合并 ACK 允许网络带宽被更有效地用于传输实际的数据负载,而不是控制消息。

当延迟确认与 Nagle 算法(一种减少网络上小包数量的技术)同时使用时,可能会导致性能显著下降,特别是在交互式应用中。

尽管 Nagle 算法和延迟确认应答都旨在通过减少网络上的包数量来提高效率,但它们各自针对的是发送方和接收方的不同方面。Nagle 算法试图减少发送的小包数量,而延迟确认应答试图减少发送的确认包数量。

携带应答

携带应答的基本思想是将确认信息(ACK)附加到正常的数据包中,而不是单独发送一个只包含 ACK 的包。这种方法在双向持续通信的场景中尤为有效,因为它可以显著减少因发送确认而产生的网络流量。

例如,在一个 TCP 会话中,客户端发送数据包到服务器,服务器在处理请求的同时,也需要向客户端发送响应数据。在这种情况下,服务器的响应数据包可以附加一个 ACK,确认它已经收到客户端的一部分或全部数据,而不是单独发送一个确认包。

携带应答通过减少必须发送的总包数,它可以减轻网络负载,虽然它减少了数据包的数量,但每个数据包的大小可能增加,这在某些网络条件下可能导致数据包碎片化问题。

数据包碎片化指的是大的数据包在发送过程中被分割成更小的单元以适应网络中的最大传输单元(MTU)的过程。这个问题我们前面的内容中已经讲到。

假设有如下的场景,一个客户端和服务器正在进行 HTTP 会话:

  1. 客户端发送了一个 HTTP 请求到服务器。

  2. 服务器接收到请求后,准备发送 HTTP 响应。

  3. 在不使用携带应答的情况下,服务器可能先发送一个 ACK 确认接收到请求,随后再发送 HTTP 响应。

  4. 使用携带应答的情况下,服务器可以将 ACK 直接附在 HTTP 响应包中一起发送。这样,一个传输操作中就同时完成了数据传输和确认,从而提高了效率。

UDP

UDP(用户数据报协议,User Datagram Protocol)是一种无连接的网络通信协议,属于互联网协议套件中的一部分,常用于那些不需要或不希望维护会话状态的场景。UDP 使得计算机应用程序可以在 IP 网络中发送消息,即使网络的其他部分出现故障也不会中断。

UDP 的特点主要有以下几个方面:

  1. 无连接:UDP 不需要在数据传输前建立连接,发送数据之前不进行握手。这意味着它可以提供快速的数据传输服务。

  2. 不可靠传输:UDP 不保证消息的可靠送达,因此,接收方收到的数据包的顺序可能与发送顺序不同,数据包也可能会丢失或重复。

  3. 无拥塞控制:UDP 不进行拥塞控制,因此其网络数据的发送速度不会自动根据网络的拥塞程度调整。这可能会在网络负载高时导致数据的丢失。

  4. 数据报文服务:UDP 提供的是一个面向消息的服务,应用层数据直接封装成数据报文进行发送,每个数据报都是独立处理的。

  5. 支持多播和广播:UDP 支持发送单播、多播及广播消息。

它的优点主要有以下几个方面:

  1. 低开销:由于没有连接建立、维护和拆除的开销,UDP 的头部开销小,适合传输小量数据。

  2. 高速传输:不进行拥塞控制和流量控制,可以快速发送数据,适合对实时性要求高的应用。

  3. 灵活性:多播和广播的支持使 UDP 在某些应用场景下更为有效。

它的缺点主要有以下几个方面:

  1. 不保证可靠传输:数据可能丢失、错误或重复,且发送与接收的数据包顺序可能不一致。

  2. 缺乏流量控制:可能导致网络拥塞,对网络其他部分的影响较大。

  3. 安全性:UDP 相对简单,不包括内建的加密或完整性检查机制。

UDP 洪水

UDP 洪水攻击(UDP Flood Attack)是一种常见的分布式拒绝服务(DDoS)攻击方法,攻击者通过大量的 UDP 数据包来洪泛目标系统或网络,消耗目标资源(如带宽和处理能力),从而使正常用户无法访问目标系统或服务。

UDP 洪水攻击的核心是发送大量的 UDP 包到目标系统的随机端口:

  1. 攻击启动:攻击者通常使用多个被控制的设备(被称为僵尸网络)向目标发送大量的 UDP 数据包。

  2. 随机端口:这些 UDP 数据包通常发送到目标机器的随机端口上。当目标系统接收到这些请求后,会检查对应端口上是否有应用在监听。

  3. 无应用响应:如果没有应用监听这个端口,目标系统就会生成一个"ICMP 端口不可达"消息,并将其发送回源地址。

  4. 资源消耗:这一过程消耗目标机器的网络带宽、处理能力以及内存,重复这一过程可以迅速耗尽目标系统的资源,从而导致服务不可用或系统崩溃。

UDP 洪水攻击可以分为几种类型,主要包括:

  1. 直接攻击:攻击者直接从一个或几个点发送大量 UDP 包到目标系统。

  2. 反射攻击:攻击者利用第三方系统向目标反射 UDP 流量。例如,攻击者向大量的 DNS 服务器发送请求,但是伪造源 IP 地址为目标的地址,使得所有的响应都发送到目标系统。

  3. 放大攻击:结合反射的原理,利用具有放大效果的协议和服务(如 DNS、NTP 等)发送小的查询请求,但引发大量的响应数据包被发送到目标系统。

防御 UDP 洪水攻击可以采取多种策略:

  1. 流量监控和异常检测:使用流量监控工具来分析网络流量,实时检测和响应异常流量模式。

  2. 带宽扩展:虽然这不是一个长期的解决方案,增加带宽可以在某种程度上抵御低至中等强度的攻击。

  3. 基于行为的防御系统:部署入侵检测系统(IDS)和入侵预防系统(IPS)可以帮助检测并阻断恶意流量。

  4. 配置网络设备:配置边界路由器和防火墙规则,限制进入网络的 UDP 流量,特别是那些目的端口为非业务相关端口的流量。

  5. 反射/放大源的缓解:对于反射和放大攻击,减少网络对外部无效查询的响应,例如配置 DNS 服务器不响应非局域网内的请求。

  6. 云基础 DDoS 保护:利用云服务提供的 DDoS 保护工具,这些工具能够在更大的带宽和资源池中分散攻击流量的影响。

UDP 洪水是一种有效的 DDoS 攻击手段,通过消耗目标的网络资源来达到拒绝服务的目的。由于 UDP 是一种无连接的协议,这使得攻击的发起既简单又难以追踪到具体的来源。防御这种攻击需要一个多层次的安全策略,结合技术和组织措施来提高整体的网络安全态势。

数据段和数据报

在网络协议中,特别是在 TCP/IP 协议栈中,数据段和数据报是两个核心概念,它们在不同的层次上对数据进行封装,具体表现为 TCP 使用数据段(Segment)而 UDP 使用数据报(Datagram)。

数据段(Segment)

数据段是传输层(TCP/IP 模型中的第四层)的数据单位,主要与 TCP(传输控制协议)关联。数据段的设计目的是为了提供一个可靠的、面向连接的数据传输服务。TCP 协议通过序列号、确认响应、流量控制、拥塞控制等机制,保证数据能够按序、完整地到达接收方。

一个 TCP 数据段通常包括:

  1. TCP 头部:包含源端口和目标端口、序列号、确认号、数据偏移、控制标志(如 SYN、ACK、FIN 等)、窗口大小、校验和及紧急指针等字段。

  2. 数据负载:承载上层应用程序的数据。

数据报(Datagram)

数据报是传输层的数据单位,主要与 UDP(用户数据报协议)关联。UDP 提供一种无连接的服务,它不保证数据的可靠性、顺序或重复数据的检测。UDP 的设计目标是简洁性和传输效率,适用于对传输速度要求较高、但可以容忍一定数据丢失的应用,如视频播放和在线游戏。

一个 UDP 数据报包括:

  1. UDP 头部:包含源端口和目标端口、数据报长度和校验和。

  2. 数据负载:承载上层应用程序的数据。

两者区别

特性 TCP 数据段 UDP 数据报
连接类型 面向连接的 无连接的
可靠性 高(通过 ACK 和序列号保证) 低(不保证消息送达)
头部开销 较大(至少 20 字节) 较小(8 字节)
使用场景 需要可靠传输的应用 需要快速传输的应用
控制机制 有(流量控制、拥塞控制)

总结

传输层位于计算机网络的 OSI 模型第四层,主要负责实现端到端的数据传输服务。它通过 TCP 和 UDP 两种主要协议,提供从可靠的连接导向的传输到快速的无连接服务。主要功能包括错误检测、数据分段与重组、流量控制以及拥塞控制。传输层的有效管理对于确保不同网络应用的性能和可靠性至关重要,特别是在面对需求各异的网络通信环境时。

相关推荐
Marst Code4 分钟前
(Django)初步使用
后端·python·django
代码之光_198010 分钟前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端
编程老船长23 分钟前
第26章 Java操作Mongodb实现数据持久化
数据库·后端·mongodb
IT果果日记44 分钟前
DataX+Crontab实现多任务顺序定时同步
后端
SizeTheMoment1 小时前
初识HTTP协议
网络·网络协议·http
安冬的码畜日常1 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记2 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java2 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
姜学迁2 小时前
Rust-枚举
开发语言·后端·rust