为何TCP被动关闭端不需要TIME_WAIT状态?

来自:车小胖谈网络?(微信号:chexiaopangnetwork),作者:车小胖谈网络

主动关闭端进入TIME_WAIT状态等2MSL,是为了防止本端发出的ACK丢失,给对端重新发送FIN,本端重新ACK的机会。

那被动关闭端也有可能发出了ACK对端没收到,为什么不需要进入类似TIME_WAIT的状态,而是直接CLOSED了呢?这种情况下,对端也即主动关闭端是否会一直停留在CLOSING状态?

对问题补充说明下,我能理解被动端发出的FIN会等待对端ACK,我的疑问是被动端发出的ACK如何确保主动端会收到?难道主动端要同时收到ACK和FIN才会ACK,而不是收到了FIN就回ACK吗?

?

?

先说结论:不需要,因为是画蛇添足!

?

之所以回答这个问题,有两点原因:

?

  • 认真思考之后的提问,这样才有讨论的意义

  • TCP协议非常重要,讨论重要的内容才有价值

?

请看下图的右下部分,代表被动关闭方的状态变迁,一共四种状态。

?

  • ESTABLISHED

  • CLOSE_WAIT

  • LAST_ACK

  • CLOSED

?


为了使整个描述过程生动一些,采用拟人的手法。主动关闭方为Bob,被动关闭方为Alice,以下简称Alice、Bob。

?

由于这个问题使关于被动关闭方Alice,所以只描述Alice状态变迁。

?

ESTABLISHED

Bob与Alice建立了TCP连接,双方状态同步为“ESTABLISHED”。此时,TCP连接可以双向传输字节数据。

?

Bob收到了主人(应用程序)的关闭连接指令,这个关闭指令有两层含义:

?

  • 主人的数据全部发送完毕

  • 主人希望释放掉当前TCP连接占用的内存

?

Bob不敢丝毫迟疑,立马组织好TCP报文,其中关键的元素有2个部分:

?

FIN状态位置 “1”

Sequence Number = X

?

Bob将TCP报文发出,顺利到达Alice,Alice的状态有没有变?

?

没变,依然是“ESTABLISHED”状态。

?

尽管状态没有变,但是Alice已经忙开了。Alice连忙给自己的主人(应用程序)发个消息:

?

老大,对方要关闭连接,请您指示!

?

老大通常有两种回答:

?

  1. 先敷衍一下对方,我这里还有一点数据需要继续发送,等发送完毕通知你!

  2. 我没有数据要发送了,请关闭连接!

?

?Alice听后分别有两种不同的处理,分别变迁两种不同的状态。

?

CLOSE_WAIT

针对老大第一种回答,只ACK对方,并不发送关闭连接(FIN)信号,因为老大还有数据需要发送。

?

重点来了,Alice 是如何ACK对方的呢?

?

ACK位置“1”,对吗?

?

不完全对,这不是重点!

?

重点是 “Acknowledgement Number”填入什么值?

?

如果Bob发的FIN报文没有字节数据,那么Alice的Acknowledgement Number = Bob 的Sequence Number + 1 = X + 1。

?

如果Bob发的FIN报文携带有m个字节数据,那么Alice的Acknowledgement Number = Bob 的Sequence Number + m + 1 = X + m + 1。

?

发完该TCP报文,即进入CLOSE_WAIT状态,即等待老大同意关闭连接。

?

稍后老大发送完数据,通知Alice可以关闭。Alice走第二种回答的流程,进入“LAST_ACK”状态!

?

LAST_ACK

针对老大第二种回答,不仅要ACK对方,还要发送关闭连接(FIN)信号。

?

  • FIN位置“1”

  • Sequence Number =Y

  • Acknowledgement Number = X + 1??或 X + m + 1

?

发完该TCP报文,即进入LAST_ACK状态,即等待对方ACK己方发出的这个FIN报文。

?


Bob收到Alice的FIN报文,立马将自己的ACK报文发出,报文的格式为:

?

  • ACK位置“1”

  • Acknowledgement Number = Y + 1??或Y + n + 1

?

Acknowledgement Number是Y + 1还是Y + n + 1取决于Alice的FIN报文是否有字节数据(n个字节长)。

?

Alice收到该报文,会清晰地知道,自己的FIN报文已经安全抵达Bob,因为Acknowledgement Number告知了这个事实。

?

CLOSED

Alice瞬间将自己的状态位切换到CLOSED状态,TCP连接占用的内存被系统释放。

?

最后一个问题,Alice在没有收到Y + 1或Y +n + 1确认号之前,是不可能切换到CLOSED状态的!会一直逗留在LAST_ACK状态,重传定时器(retransmit timer)会周期性地重传Alice的FIN报文。

?

如果很幸运,在多次重传之后收到了Y + 1或Y + n + 1确认号,立马切换到CLOSED状态。

如果很不幸,到达重传上限之后依然没有收到Y + 1或Y + n + 1确认号,Alice会单方面Reset掉当然连接,并释放内存!

推荐↓↓↓
程序员的那点事
上一篇:计算机之父,你知道是谁吗? 下一篇:互联网灾难回顾(一)