目录
一、基本概述
上篇博客( 计网第五章(运输层)(七)(TCP的连接建立))总结了TCP连接建立。
既然有连接建立就肯定有连接释放。
TCP连接释放采用"四次挥手"的方式,即客户和服务器之间需要交换四个报文段。
二、具体实现
**(1)初始状态(连接已建立状态):**如图,客户端和服务器端处于连接已建立状态。双方可以进行数据传输。
**(2)客户端发送TCP连接释放报文段:**如图,使用TCP客户进程的用户进程通知其主动关闭TCP连接。TCP客户进程会发送TCP连接释放报文段。并进入终止等待1状态(FIN-WAIT-1)。很明显,这是主动关闭。
该报文段首部中的终止位FIN和确认位ACK的值都被设置为1,表示这是一个TCP连接释放报文段。同时也对之前收到的报文段进行确认。序号字段seq的值为u,该值为TCP客户进程之前已传送过的数据的最后一个字节的序号加1。确认号字段ack的值为v,该值为TCP客户进程之前已收到的数据的最后一个字节的序号加1。
注意:终止位FIN为1的报文段即使不携带数据,也要消耗掉一个序号。
**(3)服务器端发送TCP确认并进入半关闭状态:**服务器端收到TCP连接释放报文段后,会发送一个普通的确认报文段,并进入关闭等待状态(CLOSE-WAIT)。
报文段的序号字段seq的值为v,表示TCP服务进程之前已经发送过的数据的最后一个字节的序号加1。(该值也就是之前TCP客户进程收到的数据的最后一个字节的值,即TCP连接释放报文段里面的确认号的字段的值v)确认号字段ack的值为u+1,这是对TCP连接释放报文段的确认。
TCP服务进程这时候会通知高层应用进程:TCP客户进程要与自己断开连接了。此时,TCP客户进程到TCP服务进程这个方向的连接就释放了。这时的TCP连接属于半关闭状态,也就是TCP客户进程已经没有数据要发送了。
但是TCP服务进程到TCP客户进程这个方向的连接还没有断开,所以这时候如果TCP服务进程有数据要发送,TCP客户进程仍需要接收。
注意: 半关闭状态下,TCP客户进程只是不能再主动地发送报文段,但是如果TCP服务进程向其发送报文段,它接收后仍然会向TCP服务进程返回一个针对该报文段的确认报文段。
如果是关闭状态,那么既不会发送也不会接收。
**(4)服务端发送TCP连接释放报文段:**TCP客户客户进程收到确认报文段后,进入终止等待2状态(FIN-WAIT-2)。
如果TCP服务器进程的应用进程没有数据要发送了,就会通知TCP服务进程释放连接。由于TCP连接释放是由TCP客户进程主动发起的,所以TCP服务进程对TCP连接释放属于被动关闭。
TCP服务进程发送TCP连接释放报文段并进入最终确认阶段(LAST-ACK)。
报文段中序号字段seq的值为w,这是因为前面说过TCP服务进程还能向客户进程发送数据,所以TCP服务进程发送的最后一个报文段不一定就是上面对TCP客户进程发送的TCP连接释放报文段的确认报文。 但是因为TCP客户进程向TCP服务进程的连接已经关闭了,所以TCP服务进程收到的最后一个报文段一定就是TCP客户进程发送的TCP连接释放报文段,所以确认号字段ack的值仍然为u+1,也就是对TCP释放连接报文段的重复确认。
**(5)客户端发送确认报文段:**TCP客户进程收到来自TCP服务进程的TCP连接释放报文段之后,必须针对该报文段返回一个普通确认报文段。
报文段的序号字段seq的值为u+1,因为TCP连接释放报文段虽然不消耗数据,但要消耗掉一个序号,所以该报文段的起始序号应该为u+1。确认号字段ack的值为w+1,表示这是对TCP连接释放报文段的确认报文段。
**(6)进入关闭状态:**TCP服务进程收到确认报文段之后进入关闭状态,但是TCP客户进程要等待2MSL才能进入关闭状态。MSL指的是最长报文段的寿命。TCP允许不同实现可根据具体情况使用更小的MSL值。
三、经典问题之为什么客户进程不直接进入关闭状态?
假设TCP客户进程发送完最后一个确认段后直接进入关闭状态。那么应该就是下图:
现在设想一种情况,如果该确认报文段丢失了呢?
那么TCP服务进程肯定会进行超时重传,而TCP客户进程已经关闭了,所以不会理睬该报文段,而TCP服务进程则一直重复进行超时重传的操作。
所以设置一个时间等待状态可以保证TCP服务进程可以收到最后一个TCP确认并进入关闭状态。并且2ML的时间可以保证TCP客户进程本次TCP连接所发送的报文段在网络中全部消失,这样下次进行TCP连接,网络中就不会有旧连接的报文段。
四、保活计时器
如果TCP双方已经建立了连接,过程中TCP客户进程所在的主机出现了故障,所以通过保活计时器防止这种情况出现后TCP服务进程一直等待客户进程传输数据。
每次TCP服务进程收到TCP客户进程的数据之后,就重新设置并启动保活计时器。如果一直到超时都没收到来自客户进程的数据,那么TCP服务进程就会向TCP客户进程发送一个探测报文段,以后每隔75秒发送一次,若连发10个探测报文段都没有TP客户进程的响应,TCP服务进程就认为TCP客户进程出现了问题,随之关闭该连接。