TCP四次挥手

四次挥手过程中状态名词

参考链接:https://blog.csdn.net/xwdpepsi/article/details/8097238

ESTABLISHED:代表一个打开的连接,数据可以传给用户

FIN-WAIT-1:等待远程TCP的连接中断请求,或先前的连接中断请求的确认

FIN-WAIT-2:从远程TCP等待连接中断请求

CLOSED-WAIT:等待从本地用户发来的连接中断请求

CLOSING:等待远程TCP对连接中断的确认

LAST-ACK:等待原来发向远程TCP的连接中断请求的确认

TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认

CLOSED:没有任何连接状态


四次挥手的简单过程

刚开始客户端和服务端都处于ESTABLISHED的状态(可以进行数据传输),假如是客户端先发起断开连接请求,则:

  • 第一次挥手,客户端请求断开,发送FIN,seq=u
  • 第二次挥手,服务器端确认客户端的断开请求,返回ACK,ack=u+1,seq=v
  • 第三次挥手,服务器请求断开,返回FIN,ACK,ack=u+1,seq=w
  • 第四次挥手,客户端确认服务器的断开,发送ACK,ack=w+1,seq=u+1

在这四次挥手的过程中,ACK标志一直等于1

ack和seq的计算参考链接:https://blog.csdn.net/HappyRocking/article/details/78198776


四次挥手过程图

过程解析:

  • 第一次挥手:客户端发送一个FIN=1的TCP报文,报文中会指定一个序列号:seq=u,此时客户端FIN_WAIT_1的状态
  • 第二次挥手:服务端收到FIN报文后,会返回一个ACK报文,ack的值设置为客户端发送的u+1,以及发送一个自己的序列号seq=v,表明已经收到客户端FIN(想要断开连接的请求),此时服务端存处于CLOSED_WAIT的状态。
  • 第三次挥手:此时客户端收到服务端的确认结果后,进入了FIN_WAIT_2状态,如果服务端也想断开连接,和客户端第一个挥手一样,发给客户端一个FIN=1的TCP报文给客户端,此时依然会再发送一个ACK=1,确认序列号依然时u+1,此时的序列号seq=w,服务端进入LAST-ACK(最后确认状态)
  • 第四次握手:客户端收到服务端发来的FIN=1的TCP报文后,会再返回一个ACK=1的报文作为应答,且把服务端在第三次挥手发来的序列号作为ack的值(ack = w+1, 包确认机制中在发送连续包时,只需要对最后一次发送的数据包进行确认),此时客户端处于TIME_WAIT状态。需要等待一段时间(最长两个报文的时间——以确保服务端收到自己的ACK报文之后才会进入CLOSED状态,只要服务端不发消息,就默认其收到了),服务端这边收到来自客户端的ACK报文后,就处于关闭连接状态(CLOSED)

为什么三次握手,需要四次挥手

参考链接:https://blog.csdn.net/daocaoren1543169565/article/details/80535949

对于建立连接时的三次握手的过程中:因为当服务端收到客户端的SYN连接请求报文后,服务端返回SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的,这两个TCP报文可以直接一起返回

对于关闭连接时:当服务端收到FIN报文时,仅仅表示客户端不能发送数据了,但还能接收数据,服务端这边也未必将全部数据都发送给客户端了,所以不会立即关闭SCOKET,所以只能先回复一个ACK报文,告诉客户端,"你发的FIN报文我收到了"。只有等到我(服务端)所有报文都发送完了,我才能发送FIN报文,因此不能将两个报文一起发送,所以需要四步握手


为什们客户端发送ACK之后不直接关闭,需要等待一段时间才关闭

参考链接:https://www.jianshu.com/p/0a81dfb307d7

主要目的是:确保服务端已经收到客户端发送的ACK报文,如果没有收到的话,服务端会重新发送FIN+ACK报文(重新进入第三次挥手状态),客户端再次收到FIN报文,就知道发送给服务端的ACK报文丢失了,然后再次发送ACK报文

如果客户端不等待一段时间,而是发完ACK立即释放连接,则无法收到服务端重传的FIN+ACK报文,也不会重传ACK报文,这样服务端无法正常进入CLOSED状态


为什么等待的时间至少是2MSL(一个报文的来回时间)才关闭

参考链接:https://blog.csdn.net/yrx420909/article/details/104483591/

MSL最长报文段寿命Maximum Segment lifetime, MSL = 2

客户端一般会设置一个计时,如果超过了这个时间没有再次收到FIN+ACK报文,则代表服务端已经成功接收了ACK报文,然后客户端可以直接进入CLOSED状态

设置这个等待时间的原因:

1)保证客户端发送的最后一个ACK报文能够达到服务端

这个ACK报文有可能会丢失,使得处于服务端收不到对已发送的ACK+FIN报文的确认,服务端超时重传FIN+ACK报文,这样服务端能在2MSL的时间内收到这个重传的FIN+ACK报文,然后客户端重传一次ACK报文,再重新启动2MSL计时器,最后客户端和服务端都进入CLOSED状态

2)防止已经失效的请求报文段出现在新连接中

客户端在发送完最后一个ACK报文段,再经过2MSL,就可以使本连接持续时间内所产生的所有报文从网络消失,使得下一个新的连接中不会出现上一次连接中旧的报文段

posted @ 2021-03-16 09:56  简约的信仰  阅读(131)  评论(0编辑  收藏  举报