我发现有个公司面试的时候问了对TCP协议比较细节的地方,那就写一下帮助本身加深理解和记忆。在开始说TIME_WAIT状态以前,要知道TCP协议是如何关闭链接的。
不少人对TCP协议的三次握手都很熟悉(不知道的能够参考我之前的帖子),由于学校的垃圾考试都爱考三次握手,可是不少知道三次握手的人都对TCP协议是如何关闭链接不了解。不说废话了,TCP关闭链接过程以下图,寡人用photoshop画的,凑合看一下:
为了方便描述,我给这个TCP链接的一端起名为Client,给另一端起名为Server。上图描述的是Client主动关闭的过程,FTP协议中就这样的。若是要描述Server主动关闭的过程,只要交换描述过程当中的Server和Client就能够了,HTTP协议就是这样的。 面试
描述过程:
Client调用close()函数,给Server发送FIN,请求关闭链接;Server收到FIN以后给Client返回确认ACK,同时关闭读通道(不清楚就去看一下shutdown和close的差异),也就是说如今不能再从这个链接上读取东西,如今read返回0。此时Server的TCP状态转化为CLOSE_WAIT状态。
Client收到对本身的FIN确认后,关闭 写通道,再也不向链接中写入任何数据。
接下来Server调用close()来关闭链接,给Client发送FIN,Client收到后给Server回复ACK确认,同时Client关闭读通道,进入TIME_WAIT状态。
Server接收到Client对本身的FIN的确认ACK,关闭写通道,TCP链接转化为CLOSED,也就是关闭链接。
Client在TIME_WAIT状态下要等待最大数据段生存期的两倍,而后才进入CLOSED状态,TCP协议关闭链接过程完全结束。 网络
以上就是TCP协议关闭链接的过程,如今说一下TIME_WAIT状态。
从上面能够看到,主动发起关闭链接的操做的一方将达到TIME_WAIT状态,并且这个状态要保持Maximum Segment Lifetime的两倍时间。为何要这样作而不是直接进入CLOSED状态? socket
缘由有二:
1、保证TCP协议的全双工链接可以可靠关闭
2、保证此次链接的重复数据段从网络中消失 tcp
先说第一点,若是Client直接CLOSED了,那么因为IP协议的不可靠性或者是其它网络缘由,致使Server没有收到Client最后回复的ACK。那么Server就会在超时以后继续发送FIN,此时因为Client已经CLOSED了,就找不到与重发的FIN对应的链接,最后Server就会收到RST而不是ACK,Server就会觉得是链接错误把问题报告给高层。这样的状况虽然不会形成数据丢失,可是却致使TCP协议不符合可靠链接的要求。因此,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,可以保证对方收到ACK,最后正确的关闭链接。 函数
再说第二点,若是Client直接CLOSED,而后又再向Server发起一个新链接,咱们不能保证这个新链接与刚关闭的链接的端口号是不一样的。也就是说有可能新链接和老链接的端口号是相同的。通常来讲不会发生什么问题,可是仍是有特殊状况出现:假设新链接和已经关闭的老链接端口号是同样的,若是前一次链接的某些数据仍然滞留在网络中,这些延迟数据在创建新链接以后才到达Server,因为新链接和老链接的端口号是同样的,又由于TCP协议判断不一样链接的依据是socket pair,因而,TCP协议就认为那个延迟的数据是属于新链接的,这样就和真正的新链接的数据包发生混淆了。因此TCP链接还要在TIME_WAIT状态等待2倍MSL,这样能够保证本次链接的全部数据都从网络中消失。 大数据
各类协议都是前人千锤百炼后获得的标准,规范。从细节中都能感觉到精巧和严谨。每次深刻都有同一个感受,精妙。 spa