在TCP四次挥手中,为什么客户端发送FIN后,还可以发送报文

在TCP四次挥手中,为什么客户端发送FIN后,还可以发送报文

首先回顾下四次挥手的过程。

Snipaste_2022-06-30_14-54-53.jpg

  • 第一次挥手:客户端停止发送数据,主动关闭 TCP 连接,处于FIN_WAIT1状态,等待服务端确认。
  • 第二次挥手:服务端发送 ACK 报文,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态,等待从本地用户发来的连接中断请求。此时的 TCP 处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待 2)状态,等待服务端发出的连接释放报文段。
  • 第三次挥手:如果服务端也想断开连接了(没有要向客户端发出的数据),和客户端的第一次挥手一样,发送 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态,等待客户端的确认。
  • 第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答(ack = w+1),且把服务端的序列值 +1 作为自己 ACK 报文的序号值(seq=u+1),此时客户端处于 TIME_WAIT (时间等待)状态。

注意 !!!这个时候由服务端到客户端的 TCP 连接并未释放掉,客户端需要经过时间等待计时器设置的时间 2MSL(MSL是报文在网络上可以存活的最长时间,这个值会根据实际网络情况动态变化) 后才会进入 CLOSED 状态,这样做的目的是确保服务端收到客户端发送的 ACK 报文。如果服务端在规定时间内没有收到客户端发来的 ACK 报文的话,服务端会重新发送 FIN 报文给客户端,客户端再次收到 FIN 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文给服务端。服务端收到 ACK 报文之后,就关闭连接了,处于 CLOSED 状态。

在第二次挥手后,TCP 处于半关闭状态,客户端到服务端的连接释放,但是第四次握手仍需客户端给服务端发送报文,所以半关闭状态和发送报文是不冲突的。因为 FIN 状态位表示发送后,当前客户端仍然会接收服务器的数据,但是不会接收他本地服务的数据(应用层的数据),所以客户端在发送 FIN 后仍然能发送 ack 是不矛盾的,因为 ack 不是本地服务的数据,是放在 tcp 头部的,而不是body中。

posted @ 2022-06-30 15:10  のNice  阅读(1678)  评论(0编辑  收藏  举报