TCP的连接释放
为更好了解挥手过程,你需要理解握手过程。点这里
1. 过程简单描述
数据传输结束后,通信的双方都可以释放连接,此时,客户机A和服务器B都处在ESTABLLISHED(已建立连接)状态。
①. A的应用进程先向TCP发出连接释放报文段,并停止发送数据,主动关闭TCP连接。A把连接释放报文段首部的 FIN 置 1,其序号 seq = u,它等于前面已传送过的数据的最后一个字节的序号加 1。这时,A进入FIN-WAIT-1(终止等待1)状态,等待服务器B的确认。
(注:TCP规定,FIN报文段即使不携带数据,也会消耗一个序号。)
②. B收到连接释放报文段后即发出确认,确认号为ack = u+1,而这个报文段自己的序号是 v,等于 B 前面已传送过的数据的最后一个字节的序号加 1。之后B就进入CLOSE-WAIT(关闭等待)状态。——>这时,TCP服务器进程应通知高层应用进程,因而从A到B这个方向的连接就释放了,TCP连接此时处于半关闭(half-close)状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收。也就是说,从B到A这个方向的连接并没有关闭。
③. A收到来自B的确认后,进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。——>这时,B发出的连接释放报文段必须使FIN = 1,假定B的序号为 w(在半关闭状态B可能又发送了一些数据),B还必须重复上传已发送过的确认号ack = u+1。——>这时,B进入LAST-ACK(最后确认)状态,等待A的确认。
④. A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK 置 1 ,确认号 ack = w+1,而自己的序号是 seq = u+1(注:TCP标准,前面发送过的FIN报文段要消耗一个序号)——>此时,A进入TIME-WAIT(时间等待)状态。注意,现在 TCP 连接还没有释放掉。必须经过 时间等待计时器(TIME-WAIT timer)设置的时间 2MSL 后,A 才进入CLOSED 状态。(注:时间 MSL 叫做最长报文段寿命,RFC 793建议设置为2分钟,对于如今的网络来说,2分钟太长了,因此TCP允许不同的实现可以根据具体的情况使用更小的MSL 值。)——>所以,从A进入TIME-WAIT状态后,要经过4分钟才能进入CLOSED状态,才能开始建立下一个新的连接。——>当A撤销了相应的传输控制块TCB后,就结束了这次的TCP连接。
B只要收到了A发出的确认,就进入了CLOSED状态,同样,B在撤销相应的传输控制块TCB后,就结束了这次的TCP连接。B 结束TCP连接的时间比 A 要早一些。
上述的 TCP 连接释放过程就是四次挥手,也可以看成是两个二次挥手。
那么问题来了:
为什么 A 在 TIME-WAIT 状态必须等待 2MSL 的时间?
理由: 第一,为了保证A发送的最后一个 ACK报文段能过到达B。这个ACK报文段可能丢失,因而使处在 LAST-ACK状态下的B收不到对已发送的 FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在 2MSL时间内收到这个重传的 FIN+ACK报文段。接着, A 重传一次确认,重新启动 2MSL计时器。最后,A 和 B 就能都正常的进入CLOSED状态。如果A在TIME-WAIT状态下不等待一段时间,而是在发送完ACK报文段之后立即释放连接,那么无法收到B重传的FIN+ACK,因而也不会再发送一次确认报文段,那么。B就无法按照正常的步骤进入CLOSED状态。
第二,为了防止“已失效的连接请求报文段”出现。A在发送完最后一个ACK报文段后,经过时间2MSL后,就可以使本连续的时间内所产生的所有报文段(包括旧的连接请求报文段)都从网络上消失。
了解:什么是保活计时器?
服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是 两小时。若两小时没有收到客户的数据,服务器就发送一个探测报文段。以后则每隔75 分钟发送一次,若一连发送 10个探测报文段后仍无客户的响应,服务器就会认为客户端除了故障,接着关闭了连接。所以说,保活计时器就是为了处理在客户端出了故障的时候,让服务器不再白白等下去而浪费资源。