描述过程:
client调用close函数,给server发送FIN,请求关闭连接,server受到FIN之后给
client返回确认ACK,同时关闭读通道(这里可以参考shutdown和close的差别)
也就是说现在不能再在client上读取东西了,现在的read返回0,此时的server的tcp
状态转化为CLOSE_WAIT状态
client受到对自己的FIN确认后,关闭写通道,也就是不再向服务器发送东西了,
接下来,server调用close来关闭连接,给client发送FIN,client收到后给server回复
ACK确认,同时client关闭读通道,即不再获取客户的信息,进入我们要讨论的TIME_WAIT状态
server接收到client对自己的FIN的确认ACK,关闭写通道,TCP转化为CLOSED,也就是关闭
连接
从上面可以看到,主动发起关闭连接的一方将达到TIME_WAIT状态,这个状态持续
2*Maximum Segment Lifetime时间,为什么是这样而不是直接进入closed状态呢
原因:
1,保证TCP全双工连接能够可靠关闭
2,保证这次连接的重复数据段从网络中消失
第一点: 如果client直接进入closed了,那么由于IP协议不可靠性或者是其他网络的原因,
导致Server没有收到Client最后回复的ACK。那么,Server就会在超时之后继续发送
FIN,由于此时client若已经进入CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST
而不是ACK,server就会以为这是连接错误吧问题报告给高层。这样的情况虽然不会造成数据的丢失,导师却导致了协议
不符合可靠连接的要求,所以,client不是直接进入closed,而是保持TIME_WAIT,当
再次收到FIN时候,能够保证对方收到ACK,最后正确地关闭连接
第二点: 如果CLient直接CLosed,然后又再向Server发起一个新连接,我们不恩能够
保证这个新连接与刚刚关闭的接连的端口是不同的,也即有可能是与上次刚刚的连接的端口是相同的。
这样,假设前一次连接的某些数据仍然留在网络中,这些延迟数据在若在建立了新连接
之后才到达Server,由于新连接和老连接端口是一样的,又由于TCP协议判断不同的连接
依据是一句socket pair即(IP+端口),于是,TCP协议就任务那个延迟的数据时属于新连接的,这样就和正在
的新连接的数据报发生混淆,所以,TCP连接还要在TIME_Wait状态等等,这样可以保证这次的连接的所有数据都从网络中消失。