释放连接:四次挥手过程?为什么要等待2MSL

在这里插入图片描述

储备知识:TCP报文段的首部格式(讲下面提到的):
1.FIN:用来释放一个连接。当FIN=1时,表示此报文段的发送方的数据已经发送完毕,并要求释放运输连接。
2. 确认ACK(acknowledgment):当ACK = 1 时确认号字段才有效。ACK = 0时确认号字段无效。
TCP规定,在连接建立后所有的报文段都必须把ACK置1
3.确认号:是期待收到对方下一个报文段的第一个数据字节的序号,占四字节。
  • 第一次挥手:客户端发送连接释放报文,并停止再发送数据,主动关闭TCP连接。连接释放报文的首部的终止控制位FIN置1,其序号seq=u(等于前面已传送的数据的最后一个字节的序号加1),此时A进入FIN-WAIT-1(终止等待1)状态,等待服务器确认。注意:TCP规定,FIN报文段即使不懈怠数据,它也消耗一个序号。
  • 第二次挥手:服务器收到连接释放报文段后即发出确认,确认为ACK = 1,确认号为ack = u + 1,序号seq = v(其值是服务器前面已传送过的数据最后一个字节的序号加1),然后服务器就进入了关闭等待(CLOSE-WAIT)状态

这时TCP连接处于半关闭状态,即客户端到服务器端这个方向的连接就释放了,即客户端没有数据要发送了,但是如果服务器端要发送数据,客户端仍要接收。

客户端在收到服务器端的确认后,就进入终止FIN-WAIT-2(终止等待2)状态,等待服务器发出的连接释放报文段。

  • 第三次挥手:如果服务器已经没有数据要发送了,此时服务器向客户端发出连接释放报文段,其FIN = 1,假设服务器序号为seq = w(在半关闭状态下服务器可能又发送了一些数据)。服务器必须重复上次以发送的确认号ack = u + 1。这时服务器进入LAST-ACK(最后确认)状态,等待客户端的确认。

  • 第四次挥手:客户端在收到服务器端发出的连接释放报文段后,必须对此发出确认,在确认报文段中将ACK置位1,确认号ack = w + 1,而自己的序号是seq = u + 1。然后客户端进入TIME-WAIT(时间等待)状态。在经过时间等待计时器设置的时间2MSL后,客户端才进入关闭(CLOSE)状态。

只要服务器收到客户端发出的确认报文就进入关闭(CLOSE)状态。

回答:

  • 刚开始双方处于ESTABLISHED状态。

  • 客户端发送连接释放报文,并停止再发送数据,主动关闭TCP连接。发送后客户端变成了FIN-WAIT-1状态。注意, 这时候客户端同时也变成了half-close(半关闭)状态,即无法向服务端发送报文,只能接收。

  • 服务端接收后向客户端确认,变成了CLOSED-WAIT状态。

  • 客户端接收到了服务端的确认,变成了FIN-WAIT2状态。

  • 随后,服务端向客户端发送FIN,自己进入LAST-ACK状态,

  • 客户端收到服务端发来的FIN后,自己变成了TIME-WAIT状态,然后发送 ACK 给服务端。

  • 注意了,这个时候,客户端需要等待足够长的时间,具体来说,是 2 个 MSL(Maximum Segment Lifetime,报文最大生存时间), 在这段时间内如果客户端没有收到服务端的重发请求,那么表示 ACK 成功到达,挥手结束,否则客户端重发 ACK。

为什么客户端在TIME-WAIT装填必须等待2MSL时间呢?

  • 第一,为了保证客户端发送的最后一个ACK报文段能够到达服务端。

客户端发送的ACK报文段可能丢失,因而使服务器收不到对自己已发送的释放连接报文段的确认。服务器会重传连接释放报文段,而客户端就能在2MSL时间内收到这个重传FIN+ACK报文段。接着客户端重传一次确认,重新启动2MSL计时器。最终,客户端和服务器端都能进入CLOSE状态。

  • 第二,防止已经失效的连接请求报文段出现在本连接中。

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

为什么建立连接需要三次握手而释放连接需要四次挥手

在建立连接时,服务器端处于LISTEN状态时,当收到SYN报文段的建立连接请求后,它可以把ACK报文段和SYN报文段放在一起发送,所以在连接建立时四次握手可以合并为三次握手。(即第二次握手时,服务器的ACK报文段和SYN报文段分开发送

而在释放连接时需要四次是因为TCP连接的半关闭造成的。由于TCP是全双工的(即数据可在两个方向上同时传递),因此,每个方向都必须要单独进行关闭,这个单方向的关闭就叫半关闭。在关闭连接时,当服务器收到客户端的FIN报文通知时,它仅仅表示客户端没有数据发送服务器了;但服务器未必将所有的数据都全部发送给了客户端,所以服务器端未必马上也要关闭连接,也即服务器端可能还需要发送一些数据给客户端之后,再发送FIN报文给客户端来表示现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的,这也是为什么释放连接时需要交换四次报文了。

保活计数器

设想这样一种情况:客户端已经和服务器建立连接,但后来客户端的主机突然出现故障,显然服务器以后就不能再接受到客户端发来的数据,因此服务端不要再白白等下去。这就是保活计数器。服务器没收到一次客户的数据,服务器就重新设置这个保活计数器,时间设置通常2小时。若2小时后没有再收到客户端发送的数据,服务器就发送一个探测报文段,以后则每隔75秒发送一次,若连续发送10给个探测报文段后仍无客户端的响应,服务器就认为客户端出现故障,接着就关闭这个连接。

猜你喜欢

转载自blog.csdn.net/HZ___ZH/article/details/110134076
今日推荐