本文质量: 2 / 10(没有组织过语言,没有加图)
本文修改次数: 0
阅读时长: 7 min
TCP 四次挥手的状态
首先是TCP四次挥手,通常来讲,会分为主动关闭的一方和被动关闭的一方。
我们先假设client 主动关闭。
那么在client发送第一个fin,在server回复ack之间的这个状态,client就处于FIN_WAIT_1的状态,
client 收到server的ack之后,就处于FIN_WAIT_2的状态。
而server在受到client的fin,发出ack之后就处于被动关闭的CLOSE_WAIT 状态中了,理论上CLOSE_WAIT的时候server还是可以给客户端发消息的,因为是被动关闭。server在处于CLOSE_WAIT状态中的时候,应当主动调用close_socket() 来给client发送fin.
server在发送fin之后就处于LAST_ACK 状态,直到受到client的ack,server就认为这个连接已经关闭了。
重点是在client收到server的fin,并发送ack之后,client并不能认为这个连接已经完全终止了。此时client会处于TIME_WAIT状态,这个状态要求client在等待2* MSL之后才能认为该TCP连接已经正常关闭了。这里有一个经典的问题:
为什么是2 * MSL
通常来讲网上的答案会提到以下两点
- client不知道自己的ack是否被server收到了,有可能server收到了所以不回任何消息,也有可能server没有受到,于是server会在自client发送ack之后等待MSL秒,如果server在client发送ack之后等待了MSL秒之后还没有受到client的ack,server会重发一个fin。client等待MSL * 2 秒的作用就是保证,如果server的的确确发送了第二个FIN包,client端还会继续返回ack。否则的话,client在发送ack后直接处于close状态,server重发的FIN包到达client的时候会被认为不合法,client会回一个RST,这样server就不能正常关闭了。
那显然就有第二个问题,那如果client对于server的第二个FIN包的ack也没被server收到怎么办呢?首先可以知道的是,如果client收不到server重发的fin包,那么client就会认为连接已经正常关闭了。可是server呢,server还是收不到ack。这个时候server会怎么做?会继续重试吗,这里我猜两种情况,我得去验证,一种是server只会重发一次fin,如果一次重发fin还是收不到,那就认为这是一个不正常的连接,直接reset,还有种可能是server会重发大于等于2词的fin,并在达到一定上限后reset。我认为前面一种合理一点,否则如果第二次重发fin被client收到了,还是会被发Reset。
那万一client收到了server的第一次重发并回复ack之后,client还会继续等待吗?我看到的答案说是会的,会重新等待2 * MSL。那现在有个问题了,如果client一直能收到server重发的fin,但是server就是收不到client的ack,那怎么办?以上过程会继续重复吗?难道会一直让client 处于TIME_WAIT状态吗。 当然不是。如果server一直收不到,那我们这个连接肯定就不应该是一个正常的连接关闭。如果你是server你会怎么做?一直收不到client的ack请求,你会怎么做?(罗翔老师)你当然会在重试了几次之后发送RST,来“不正常”的关闭这个连接。所以无论怎么样,server一定会在尝试重发了几次fin之后,发送reset消息。
问题就在于,究竟是在发送几次fin之后再发送reset呢?这里是之后要看书搞明白的,有懂的朋友可以交流一下。
- 防止前一个的TCP数据包扰乱新的连接里的TCP数据包。这个比较好理解,如果不TIME_WAIT的话,client在发送ack之后立马建立新的连接,那么有可能前一个连接的幽灵数据包就会出现在第二个连接里。虽然这种可能性比较小,而且我也觉得确实难以找到这样的一个情形。
网友评论