TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

我们回顾下使用的抓包 1.1. 服务器未开 客户端尝试连接

TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

文章插图
1.2 建立连接然后关闭,断开的时候时候有时候三次握手有时候四次握手
TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

文章插图

TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

文章插图
1.3. 建立连接,交互一次然后断开
TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

文章插图
根据的包,四会握手的第二步 被动断开的一方收到FIN(第一次握手)后要发送ACK 。但是抓的包中有时候会没有这一步 。
我们看一下一般的书中TCP四次挥手的状态迁移图
当被动断开的一方发送ACK的时候,被动断开的
TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

文章插图
对于这个图大家很熟悉 。
按照这个图的顺序说明会误导大家以为断开一个TCP总是这样的 。其实按照的描述将主动断开的一方和被动断开的一方分开描述会更清晰 。
2. TCP断开连接 2.1 主动断开的一方
①首先发送FIN告诉对方我要关闭连接,自己进入到状态此时开始不再处理和发送应用层用户的数据 。
③收到对方对FIN的ACK后自己进入到,这个时候依然可以接收对方的数据 。如果收不到对方的ACK会再次发送之前包含FIN在内的消息 。进入后就等待对方关闭,因为已经确认到对方收到自己的FIN了 。
⑤收到对方的FIN说明被断开的一方也要没有数据发送并关闭连接了,此时ACK对方的FIN进入 。然后等2msl连接关闭 。
–需要注意的是,对方ACK自己的FIN后,并不会立即发送FIN而是在应用层关闭连接后才会发送FIN
2.2被动断开的一方
②收到网络中传来的FIN,自己ACK这个FIN然后进入到状态 。
④通知应用层要关闭连接(从这个角度上理解为什么断开比建立连接多了一次,因为被断开一方还有余下的数据要发送)这个时候等待用户来回应CLOSE,在发送FIN之前可以发送自己余下的数据 。发送FIN后进入 。
⑧等待对方ACK自己的FIN**完成关闭 。如果对方没确认会再次发送**FIN 。
2.3 断开过程的一些解释
(1)所以谁发送FIN谁就不再发送数据了 。
(2)发送ACK的时候,ack是收到的req的值+1 。因此第3和第4步的ack都是101 。第四步并不是102 。
(3)发送的seq是对方发送的ack所以第5步的seq是101而是不是102 。
(4)第2步后主动断开放进入是等待对方的FIN 。此时不可以发送数据但是可以接收数据 。因此FIN意味着告诉对方“我没有多余的数据要发送” 。这也是为什么断开比建立连接多一次的原因 。因为发送FIN后还可以接收数据 。
(5)被断开的一方收到FIN后,给对方发送ACK表示收到,自己状态为 。此时TCP连接处于半关闭状态 。被断开的一方仍然可以发送数据 。这时候由上一层协议应用层来决定是否要发送余下的数据 。
3. 为什么四次挥手?
TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

文章插图
我们看下断开连接的部分
TCP四次挥手之FIN_WAIT_2和CLOSE_WAIT

文章插图
3.1 实际中还会遇到的同时断开的情况和三次握手的情况 3.1.1 同时断开,同时发送FIN
同时断开的情况上面这张图是官方图 。大家可以看到后还可能先收到FIN而不是ACK 。why?因为两端可以同时关闭 。同时收到对方的FIN然后同时确认直接进入->->流程 。
3.12 三次握手,发送FIN后收到(FIN,ACK)
这张图还缺少一个状态转换就是直接收到(FIN,ACK)后到达 。这种情况是被断开的一端没有数据要发送直接发送了ACK和FIN 。这种情况通过抓包发现很常见 。也就是四个过程也变为了三次握手 。