diff --git a/blogs/computer_network/口水话/TCP.md b/blogs/computer_network/口水话/TCP.md index 4c93820..5d24b6f 100644 --- a/blogs/computer_network/口水话/TCP.md +++ b/blogs/computer_network/口水话/TCP.md @@ -66,3 +66,17 @@ FIN 同 SYN 报文一样,不管是否携带数据,FIN 段都需要消耗一 同理,三次握手也可以变成四次握手,只是把第二步的 SYN+ACK 拆分开来。与 FIN 不同的是,一般情况下,SYN 包都不携带数据,收到客户端的 SYN 包以后不用等待,可以立马回复 SYN+ACK,四次握手理论上可行,但是现实中并不常见。 +最后再说一下 TIME_WAIT 状态。 + +需要明确的是,只有主动断开的那一方才会进入 TIME_WAIT 状态,且会在那个状态持续 2 个 MSL(报文最大生存时间)。TIME_WAIT 存在的原因是什么呢? + +第一个原因是:数据报文可能在发送途中延迟但最终会到达。如果客户端在发送完 FIN 包后不等待直接进入 CLOSE 状态,过一段时间相同的 IP 和端口号又建立一个新的连接,这样收到的数据包就无法知道到底是旧连接的包还是新连接的包了,造成新连接数据的混乱。如果等待时间是 2 个 MSL,已经足够让一个方向上的包最多存活 MSL 秒就被丢弃,保证了在新创建的 TCP 连接以后,老连接姗姗来迟的包已经在网络中被丢弃消逝,不会干扰新连接。 + +第二个原因是确保可靠实现 TCP 全双工终止连接。关闭连接的四次挥手中, 最终的 ACK 是由主动关闭方发出,如果这个 ACK 丢失,对端将重发 FIN,如果主动关闭方不维持 TIME_WAIT 直接进入 CLOSED 状态,则无法重传 ACK,被动关闭方因此不能及时可靠释放。1 个 MSL 确保四次挥手中主动关闭方最后的 ACK 报文最终能够到达对端,1 个 MSL 确保对端没有收到 ACK 重传的 FIN 报文可以到达。 + +当然 TIME_WAIT 也带来了一些问题,比如连接表无法复用,因为处于 TIME_WAIT 的连接会存活 2MSL(60s),意味着相同的 TCP 连接四元组在一分钟之内没有办法复用。解决办法是添加 TCP 头部时间戳选项。 + +#### 重传机制 + +#### 滑动窗口 +