从0到1秒的魔法:TCP三次握手的信任故事

128 阅读20分钟

理解 TCP 协议中的三次握手及其相关机制是网络通信中的重要一环。让我们一步步了解这个过程吧!😊

什么是三次握手?

三次握手(Three-Way Handshake)是 TCP 协议在建立连接时使用的一个重要过程,用于确保连接的可靠性。它包含以下步骤:

  1. SYN:客户端向服务器发送一个 SYN(同步序列号)报文,表示希望建立连接。
  2. SYN-ACK:服务器收到 SYN 后,回应一个 SYN-ACK(同步序列号和确认序列号)报文,表示同意建立连接,并同步序列号。
  3. ACK:客户端收到 SYN-ACK 后,再发送一个 ACK(确认序列号)报文,确认连接建立。

为什么要三次握手?

三次握手的主要目的是为了确保双方都具备接收和发送数据的能力,并且确认彼此的接收能力。具体来说:

  • 确保客户端的发送和服务器的接收功能正常。
  • 确保服务器的发送和客户端的接收功能正常。
  • 防止旧的连接请求报文被服务器误认为是新的连接请求,造成混乱。

为什么不一次握手?

一次握手不能确保双方都能正常接收和发送数据。例如,客户端发送 SYN 报文后无法确认服务器是否接收到,也无法确认服务器是否能发送数据。缺乏双向确认,无法保证通信的可靠性。

为什么不二次握手?

二次握手无法解决一些潜在的问题,例如旧的 SYN 报文被误认为是新的连接请求,导致资源浪费和错误连接。此外,二次握手也无法完全确认双方的接收和发送能力。

为什么不四次握手?

三次握手已经足够确保连接的可靠性和双方的通信能力。四次握手会增加通信开销,而没有显著的好处。

状态变化

在三次握手过程中,客户端和服务器的状态变化如下:

  • 客户端状态

    • 初始状态:CLOSED
    • 发送 SYN 后:SYN-SENT
    • 收到 SYN-ACK 后:ESTABLISHED
  • 服务器状态

    • 初始状态:CLOSED
    • 收到 SYN 后:SYN-RECEIVED
    • 发送 SYN-ACK 后:SYN-RECEIVED
    • 收到 ACK 后:ESTABLISHED

状态变化示意图

sequenceDiagram
    participant Client
    participant Server
    Client->>Server: SYN
    Server->>Client: SYN-ACK
    Client->>Server: ACK

三次握手过程中的状态标志位变化

时间客户端状态服务器状态报文类型说明
t1CLOSEDCLOSED客户端和服务器初始状态
t2SYN-SENTLISTENSYN客户端发送 SYN 请求
t3SYN-SENTSYN-RECEIVEDSYN-ACK服务器收到 SYN 并发送 SYN-ACK
t4ESTABLISHEDESTABLISHEDACK客户端收到 SYN-ACK 并发送 ACK,连接建立

TCP 报头的主要字段:

字段名称意义命令行字段
源端口(Source Port)发送方的端口号sport
目标端口(Destination Port)接收方的端口号dport
序列号(Sequence Number)数据段的序列号,用于数据重组和流量控制seq
确认号(Acknowledgment Number)确认接收到的数据的下一个序列号ack
数据偏移(Data Offset)TCP 报头的长度,指示数据开始的地方offset
保留字段(Reserved)保留供将来使用,目前必须设置为0reserved
控制标志(Flags)控制数据段的标志(如 SYN, ACK, FIN 等)flags
窗口大小(Window Size)接收方愿意接收的窗口大小,用于流量控制window
校验和(Checksum)用于检验数据段的完整性checksum
紧急指针(Urgent Pointer)紧急数据的指针,指示紧急数据的结束位置urgptr
选项(Options)可选字段,用于扩展 TCP 的功能options
填充(Padding)用于确保 TCP 报头是32位的整数倍,填充无意义的数据padding

TCP传输过程常见的问题

出错

  • 校验和
  • 重传机制

重复

  • 序列号和确认号机制
  • 窗口大小控制
  • 超时重传和快速重传

丢失

  • 超时重传机制
  • 快速重传机制
  • 选择性确认

失序

  • 选择性确认

什么是出错?

出错是指在数据传输过程中,数据被篡改或丢失,导致接收方收到错误的数据。出错通常是由物理层和数据链路层的干扰引起的。

状态位变化与解决方法

出错时,接收方会检测到数据的校验和不匹配,丢弃错误数据并请求重传。解决方法是使用校验和(Checksum)和重传机制。

校验和(Checksum)

校验和是一种用于检测数据传输过程中错误的简单机制。它通过对数据执行特定的计算生成一个数值,接收方也会进行同样的计算并与发送方的校验和进行比较,如果两者不一致,就说明数据在传输过程中发生了错误。

校验和计算过程

  1. 发送方

    • 将数据分成若干个部分(通常为16位)。
    • 将这些部分加在一起,得到一个数值。
    • 计算这个数值的反码(所有位取反),作为校验和。
    • 将数据和校验和一起发送给接收方。
  2. 接收方

    • 接收到数据和校验和。
    • 使用同样的方法计算接收到的数据的校验和。
    • 将接收方计算出的校验和与发送方发送的校验和进行比较。
    • 如果两者一致,说明数据传输没有错误;否则,说明数据在传输过程中发生了错误,需要请求重传。

重传机制

重传机制用于在接收方检测到数据传输错误时,请求发送方重新发送数据。TCP 使用两种主要的重传机制:

  1. 超时重传

    • 发送方在发送数据后,会启动一个定时器。
    • 如果在定时器超时前没有收到接收方的确认报文,发送方会认为数据丢失或出错,进行重传。
  2. 快速重传

    • 接收方在检测到数据包出错或丢失时,会立即发送重复的 ACK 报文。
    • 当发送方收到三个连续的重复 ACK 报文时,立即重传对应的数据包,而无需等待超时。

在使用校验和(Checksum)和重传机制的过程中,TCP 报头(Header)中的一些字段会发生变化。这些字段主要包括序列号(Sequence Number)、确认号(Acknowledgment Number)、校验和(Checksum)等。让我们详细了解这些字段在数据传输过程中的变化情况。

校验和的计算和使用

校验和用于验证数据在传输过程中是否发生错误。它是对 TCP 报头、数据以及伪报头(包含源 IP 地址、目的 IP 地址、协议类型和 TCP 报文长度)的一种计算结果。伪报头仅用于计算校验和,不包含在实际的 TCP 报头中。

校验和计算过程

  1. 伪报头:包括源 IP 地址、目的 IP 地址、协议类型(TCP 为 6)和 TCP 报文长度。
  2. 报头和数据:包括 TCP 报头和数据。
  3. 计算和校验
    • 将伪报头、报头和数据视为若干个 16 位数值。
    • 将这些数值加在一起,如果有进位则将进位加到结果中。
    • 对结果取反,得到校验和。
    • 发送方将计算得到的校验和填入 TCP 报头中的校验和字段。
    • 接收方计算接收到的数据的校验和,并与报头中的校验和比较,以验证数据完整性。

重传机制

在重传机制中,TCP 报头中的序列号和确认号会发生变化,以确保数据的可靠传输。

超时重传和快速重传

  • 超时重传:如果发送方在一定时间内没有收到接收方的确认,发送方会重新发送数据。
  • 快速重传:当接收方检测到数据包出错或丢失时,会发送重复的 ACK 报文。发送方在收到三个连续的重复 ACK 后,会立即重传相应的数据包。

报头字段的变化

例子:校验和和重传机制的工作过程

假设客户端发送一个数据包给服务器,数据包的序列号为 1001,数据内容为 "Hello"。以下是报头字段在不同阶段的变化:

  1. 初始发送
  • 发送方(客户端)

    • 计算数据 "Hello" 的校验和,假设得到校验和为 0x1234
    • 发送数据包 [源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234, 数据="Hello"]。
  • 接收方(服务器)

    • 接收到数据包 [源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234, 数据="Hello"]。
    • 计算接收数据 "Hello" 的校验和,假设计算结果为 0x1234
    • 比较接收到的校验和 0x1234 与计算得到的校验和 0x1234,一致,数据正确。
    • 发送 ACK 包 [源端口=80, 目的端口=5000, 序列号=2001, 确认号=1002, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x5678]。
  1. 重传过程(数据包出错)
  • 发送方(客户端)

    • 发送数据包 [源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234, 数据="Hello"]。
    • 启动定时器。
  • 接收方(服务器)

    • 接收到错误数据包 [源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234, 数据="Hxllo"]。
    • 计算接收数据 "Hxllo" 的校验和,假设计算结果为 0x5678
    • 比较接收到的校验和 0x1234 与计算得到的校验和 0x5678,不一致,数据出错。
    • 丢弃错误数据包,发送重复的 ACK 包 [源端口=80, 目的端口=5000, 序列号=2001, 确认号=1001, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x5678]。
  • 发送方(客户端)

    • 收到重复的 ACK 包 [源端口=80, 目的端口=5000, 序列号=2001, 确认号=1001, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x5678]。
    • 重传数据包 [源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234, 数据="Hello"]。
    • 再次启动定时器。
  1. 重传成功
  • 接收方(服务器)

    • 接收到重传数据包 [源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234, 数据="Hello"]。
    • 计算接收数据 "Hello" 的校验和,假设计算结果为 0x1234
    • 比较接收到的校验和 0x1234 与计算得到的校验和 0x1234,一致,数据正确。
    • 发送 ACK 包 [源端口=80, 目的端口=5000, 序列号=2001, 确认号=1002, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x5678]。
  • 发送方(客户端)

    • 收到 ACK 包 [源端口=80, 目的端口=5000, 序列号=2001, 确认号=1002, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x5678]。
    • 停止定时器,确认数据包成功传输。

报头字段变化表格

时间客户端报头服务器报头说明
t1[源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234]客户端发送数据
t2[源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234]服务器接收数据,校验正确
t3[源端口=80, 目的端口=5000, 序列号=2001, 确认号=1002, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x5678]服务器发送确认
t4[源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234]客户端重传数据
t5[源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234]服务器接收重传数据,校验正确
t6[源端口=80, 目的端口=5000, 序列号=2001, 确认号=1002, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x5678]服务器发送确认
t7[源端口=5000, 目的端口=80, 序列号=1001, 确认号=0, 数据偏移=5, 控制标志=ACK, 窗口大小=4096, 校验和=0x1234]客户端停止重传,确认成功

通过上述步骤和表格,我们可以清晰地看到在使用校验和和重传机制过程中,TCP 报头字段是如何变化的。这些机制确保了数据在网络传输中的完整性和可靠性。😊

什么是重复?

重复是指同一个数据包被多次发送,接收方收到多份相同的数据包。这通常是由于网络故障或重传机制引起的。

状态位变化与解决方法

接收方可以通过序列号检测到重复数据包,并丢弃重复数据,确保数据的唯一性。

解决 TCP 通信中的重复数据包主要通过以下方法实现:

  1. 序列号和确认号机制
  2. 窗口大小控制
  3. 超时重传和快速重传

我们将详细介绍这些方法以及在过程中 TCP 报头的变化。

1. 序列号和确认号机制

原理

TCP 使用序列号(Sequence Number)来标识数据包的顺序。每个数据包都有一个唯一的序列号,接收方通过序列号来识别和丢弃重复的数据包。确认号(Acknowledgment Number)用于确认已接收的数据包,并告知发送方数据已经正确到达。

过程

  • 发送方:发送带有序列号的数据包,并等待接收方的确认。
  • 接收方:接收数据包,检查序列号。如果是新数据包,则处理并发送 ACK;如果是重复数据包,则丢弃并发送重复的 ACK。

TCP 报头变化

  • 发送方发送数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 接收方接收数据包,发送 ACK

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 80      | 5000    | 0        | 1002     | 5         | 0x5678   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 发送方未收到 ACK,重传数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    

2. 窗口大小控制

原理

TCP 使用窗口大小(Window Size)来控制发送方可以发送的未确认数据的最大数量。通过调整窗口大小,接收方可以有效地控制数据流,避免发送方过快发送数据而导致网络拥塞。

过程

  • 发送方:根据接收方的窗口大小,决定可以发送的数据量。
  • 接收方:根据接收能力,调整窗口大小并通知发送方。

TCP 报头变化

  • 发送方发送数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 接收方调整窗口大小,发送 ACK

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 80      | 5000    | 0        | 1002     | 5         | 0x5678   | 2048   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    

3. 超时重传和快速重传

原理

当发送方在一定时间内没有收到 ACK 时,会触发超时重传。快速重传是指发送方在收到三个连续的重复 ACK 时,立即重传数据包,而不等待超时。

过程

  • 发送方:发送数据包,启动定时器,等待接收方的 ACK。如果超时未收到 ACK 或收到重复的 ACK,立即重传数据包。
  • 接收方:接收到数据包后,发送 ACK。如果数据包有错误或丢失,发送重复的 ACK。

TCP 报头变化

  • 发送方发送数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 接收方发送 ACK

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 80      | 5000    | 0        | 1002     | 5         | 0x5678   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 发送方未收到 ACK,重传数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 接收方发送重复的 ACK

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 80      | 5000    | 0        | 1002     | 5         | 0x5678   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    

通过上述方法和过程,TCP 能有效检测和处理重复数据包,保证数据传输的准确性和可靠性。这些机制确保了在数据传输过程中,尽可能减少重复数据包带来的影响,提高通信效率和数据完整性。

什么是丢失?

丢失是指数据包在传输过程中被丢弃,接收方未收到数据包。这可能是由于网络拥塞或故障引起的。

状态位变化与解决方法

丢失的数据包会导致接收方未能确认数据。发送方在超时后会重新发送数据包。

在 TCP 通信中,数据包丢失是一个常见问题,通常通过以下几种方法来解决:

  1. 超时重传机制(Timeout Retransmission)
  2. 快速重传机制(Fast Retransmit)
  3. 选择性确认(Selective Acknowledgment, SACK)

我们将详细介绍这些方法及其过程,并说明在过程中 TCP 报头的变化。

1. 超时重传机制

原理

当发送方在设定的时间内未收到接收方的确认(ACK),就会重传数据包。这是最基本的一种重传机制。

过程

  1. 发送方:发送数据包,并启动定时器。
  2. 接收方:接收数据包后,发送 ACK。
  3. 发送方:如果在定时器超时前没有收到 ACK,重传数据包。

TCP 报头变化

  • 发送方发送数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 接收方发送 ACK(如果接收到数据包):

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 80      | 5000    | 0        | 1002     | 5         | 0x5678   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 发送方未收到 ACK,重传数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    

2. 快速重传机制

原理

快速重传机制在接收方收到三个连续的重复 ACK 时,发送方立即重传数据包,而不等待超时。这减少了等待时间,提高了数据传输效率。

过程

  1. 发送方:发送数据包,等待 ACK。
  2. 接收方:如果数据包有丢失,接收方会发送重复的 ACK。
  3. 发送方:收到三个重复的 ACK 后,立即重传丢失的数据包。

TCP 报头变化

  • 发送方发送数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 接收方发送重复的 ACK

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 80      | 5000    | 0        | 1001     | 5         | 0x5678   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 发送方收到三个重复的 ACK,立即重传数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    

3. 选择性确认(SACK)

原理

选择性确认允许接收方告知发送方哪些具体数据段已经成功接收,哪些还需要重传。这种机制在数据包丢失率较高的网络环境中非常有效。

过程

  1. 发送方:发送数据包,等待 ACK。
  2. 接收方:接收数据包后,发送选择性确认,标识已成功接收的段。
  3. 发送方:根据选择性确认,重传丢失的数据段。

TCP 报头变化

  • 发送方发送数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 接收方发送选择性确认

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 80      | 5000    | 0        | 1002     | 5         | 0x5678   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    
  • 发送方根据选择性确认,重传丢失的数据包

    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | Source  | Dest.   | Sequence | Ack      | Data      | Checksum | Window | Urgent |
    | Port    | Port    | Number   | Number   | Offset    |          | Size   | Pointer|
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    | 5000    | 80      | 1001     | 0        | 5         | 0x1234   | 4096   | 0      |
    +---------+---------+----------+----------+-----------+----------+--------+--------+
    

总结

通过超时重传、快速重传和选择性确认,TCP 能够有效解决数据包丢失的问题,确保数据传输的可靠性和完整性。每种方法在不同网络条件下都有其优点,综合使用这些方法,可以大大提高 TCP 通信的效率和稳定性。

什么是失序?

失序是指数据包按错序列到达接收方,接收方无法按正确顺序重组数据。这通常是由于网络路径的差异或多路径传输引起的。

状态位变化与解决方法

接收方会缓存失序的数据包,并等待缺失的数据包到达后再进行重组。

真实例子:失序过程中的状态标志位变化

时间客户端状态服务器状态报文类型说明
t1ESTABLISHEDESTABLISHEDDATA(seq=1)客户端发送数据包 1
t2ESTABLISHEDESTABLISHEDDATA(seq=3)客户端发送数据包 3
t3ESTABLISHEDESTABLISHEDDATA(seq=2)客户端发送数据包 2
t4ESTABLISHEDESTABLISHED服务器缓存数据包 3,等待数据包 2
t5ESTABLISHEDESTABLISHEDACK数据包 2 到达,服务器按顺序重组并确认

总结

TCP 三次握手通过序列号和确认机制,确保了连接的可靠性和双方的通信能力。在数据传输过程中,通过各种检测和重传机制,解决了出错、重复、丢失和失序等问题。😄