TCP连接释放的过程可称之为四次挥手,可以简单的这样理解,当建立连接时是建立了C->S和S->C,所以在释放的时候要对两边都进行释放,具体如图:
第一次挥手:C客户端的应用程序先向其TCP发出释放报文段,并且停止发送数据,主动关闭TCP连接,C把连接释放报文段的终止控制位FIN=1,其序号seq=u,这个u是前面已经传送过的数据的最后一个字节的序号+1,这个时候C进入FIN-WAIT1(终止等待1)状态,等待S的确认,TCP规定FIN段即使不携带数据,也消耗一个序号。
第二次挥手:S服务器收到释放报文段后即发出确认,确认号ack=u+1,自己报文段的序号是v,同样的v等于S传送过的最后一个字节的序号+1,然后S进入CLOSE-WAIT(关闭等待)状态,TCP服务器通知应用层,到此C->S的连接就释放了,但是这个时候的TCP连接是一种半关闭状态,就是当S向C发送数据的时候,C仍然要接收,只是C已经没有数据向S发送了。这个时候C收到了来自S的确认后,C就进入了FIN-WAIT-2(终止等待2)状态,等待S发出连接释放报文。
第三次挥手:若S没有要发送的数据了,其应用进程就通知TCP释放连接,这个时候S发出的连接释放报文段中FIN=1,现在假设S的序号是w(半关闭状态S可能还向C发送一些数据),S这个时候还是发送确认号ack=u+1,然后进入LAST-ACK(最后确认)状态,等待C的确认。
第四次挥手:C收到S的释放报文段后,必须给出确认,在确认报文段中ACK=1,seq=u+1,ack=w+1,然后进入TIME-WAIT(事件等待)状态,到现在TCP连接还没有释放,必须等待时间等待计时器设置的时间2MSL后,C才进入CLOSED状态。
为什么要设置这个2MSL?MSL是什么?
MSL指的是最长报文寿命,一般2min,设置这个2MLS
为了保证C发送的最后一个确认报文来够到达S,因为这个报文可能会丢失,当丢失的时候,S会因为收不到确认而重传FIN+ACK报文,而C可以在2MLS事件内接收到这个报文,接着C重传ACK确认报文并且重置这个2MLS。最后S和C都进入CLOSED状态。
值得注意的是S端的TCP连接断开会早于C。