为什么客户端在关闭状态时会发送RESET?

网络工程 tcp 联网 第 4 层
2022-02-20 03:47:25

假设我有一个 TCP 状态转换图。并假设最后一个 ACK​​ 丢失了。然后,B 会认为 A 没有收到 FIN,会重新发送 FIN。从 B 的角度来看,这与 FIN 丢失一样,从 A 的角度来看,这是不同的,因为 A 现在处于

案例1:TIME_WAIT

或者

Case2:关闭状态。

case1 : 当 A 从 A 接收到新的 FIN 时,如果它处于 TIME_WAIT 状态,它将再次发送 ACK(理解这一点)。

case2:如果 A 处于 CLOSED 状态,它将发送一个 RESET(不明白这个),在任何一种情况下,B 都将能够关闭其一侧的连接。

A -----FIN-----> B
FIN_WAIT_1       CLOSE_WAIT
A <----ACK------ B
FIN_WAIT_2

(B can send more data here, this is half-close state)

A <----FIN------ B
TIME_WAIT        LAST_ACK
A -----ACK-->X(Lost)   B
TIME_WAIT        LAST_ACK
|
2MSL Timer
|
CLOSED
                 (timeout waiting for ACK)
A <----FIN------ B
A -----RST-----> B
                 CLOSED

我的问题是,为什么 A 在关闭状态时发送 RST?

2个回答

参见RFC 793

重置生成

作为一般规则,每当一个显然不是用于当前连接的段到达时,必须发送重置 (RST)。如果不清楚是这种情况,则不得发送复位。

为了了解为什么会发生这种情况,我们需要考虑以下两件事:

  1. TCP 是有状态的,因为连接的两个端点都保持连接状态。当连接关闭时,必须在某个时候删除此状态。在 TCP 中,可以在(立即)切换到 CLOSE 状态时删除连接状态。

  2. 当 TCP 接收到一个段时,它必须能够将该段与任何现有连接相关联。如果没有将段关联到的连接,则 TCP 发送 RST(参见 Zac67 的答案)。

这就是这两个事实如何适用于这种情况。

A -----FIN-----> B
A <----ACK------ B

A <----FIN------ B
A -ACK ->   ???  B

A 发送了一个 ACK​​。此时,A 和 B 都关闭了连接。因此,不再需要连接状态。但是,由于最后一个 ACK​​ 可能会丢失,因此标准规定 A 必须在 2 * MSL 时间间隔内保留(部分)连接状态。如果 ACK 丢失,B 将重新发送 FIN,A 可以重新发送它的 ack。它还重置此 2*MSL 计时器。

根据标准(RFC 793):

MSL - 最大段生命周期,一个 TCP 段可以存在于互联网络系统中的时间。任意定义为2分钟

我认为某些系统允许配置该计时器的值。但是,它应该足够大,以便 FIN 的重传在计时器到期之前到达。

所以,这可能发生:

A -----ACK-->X(Lost)   B
TIME_WAIT        LAST_ACK

                 (timeout waiting for ACK) 
A <----FIN------ B
A -----ACK-----> B
|
restart 2MSL timer
|

这不应该发生。如果是,则表示计时器太短。

A -----ACK-->X(Lost)   B
TIME_WAIT        LAST_ACK
|
2MSL Timer
|
CLOSED
// timer value was too short(!)
                 (timeout waiting for ACK)
A <----FIN------ B
A -----RST-----> B
                 CLOSED

让我们看看为什么发送RST:

...
A -ACK ->   ???  B
TIME_WAIT     // A goes into TIME_WAIT state  
|
2MSL Timer
|            // The timer expires
CLOSED      // A deletes any connection state associated with this connection

因此,如果由于某种原因发生这种情况:

A <----FIN------ B

A 没有任何与此段关联的连接状态。它不知道如何处理它。因此,根据规范,它会发送其 RST。