TCP连接的释放由双方(无次序要求)各自发起的一次自身至对方方向的单向连接的释放共同完成。首先发起连接释放的一方称为主动关闭方,随后发起连接释放的一方称为被动关闭方。 连接释放过程如下: 1) 若A已无数据向B发送,A可向B发送连接释放报文段,连接释放报文段的FIN=1,序号seq=u(u为前面已传送过的数据的最后一个字节的序号加1)。 TCP规定,FIN报文段(即FIN=1的报文段)不能携带数据,但要消耗掉一个序号。这时,A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。 2) B收到A的连接释放报文段后需发出确认。确认报文段的 ACK=1,确认号ack=u+1(该1是A的连接释放报文段消耗掉的一个序号),序号seq=v(v为前面已传送过的数据的最后一个字节的序号加1)。此时,B进入CLOSED-WAIT(关闭等待)状态。从A到B这个方向的连接就释放了,此时TCP连接处于半关闭状态,即A已没有数据要发送了,但B若发送数据,A仍要接收,也即从B到A这个方向的连接还未关闭。 3) A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。 4) 若B已无数据向A发送,B可向A发送连接释放报文段,连接释放报文段的FIN=1,序号seq=w(在半关闭状态,B可能又发送了一些数据,w为前面已传送过的数据的最后一个字节的序号加1),确认号ack=u+1(重复上次已经发送过的确认号)。这时,B进入LAST-ACK(最后确认)状态,等待A的确认。 5) A收到B的连接释放报文段后需发出确认。确认报文段的ACK=1,确认号ack=w+1(该1是B的连接释放报文段消耗掉的一个序号),序号seq=u+1。这时,A进入TIME-WAIT(时间等待)状态。现在TCP连接还未释放掉,必须经过时间等待计时器设置的时间2MSL后,A才进入到CLOSED(连接已关闭)状态。 6) B收到A的确认后,就进入CLOSED状态。 说明: 1) 连接释放过程是四次握手,可看做两个两次握手。 2) 连接建立中,服务器到客户的同步是和其对客户到服务器同步的确认一块发送的,即服务器的连接响应报文段的SYN=1且ACK=1;连接释放中,被动关闭方连接释放的请求是和其对主动关闭方连接释放的确认分开发送的,故连接释放的握手次数比连接建立的握手次数多一次。【因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送;但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了,但未必你所有的数据都全部发送给对方了,所以你不可以马上关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的】 3) 连接释放允许同时释放,即双方同时发送连接释放报文段,也允许快速释放,即被动关闭方连接释放的请求和其对主动关闭方连接释放的确认一块发送。 4) 主动关闭方在TIME-WAIT状态必须等待2MSL时间的原因是: a) 保证A对B的连接释放的确认能够到达B,使B可以正常关闭,防止B一直处在LAST-ACK状态等待。若该确认报文段丢失,使得处在LASK-ACK状态的B收不到对其FIN报文段的确认,B会超时重传其FIN报文段,而A就能在2MSL时间内收到这个重传的FIN报文段。接着A重传一次确认,并重新启动2MSL计时器。最后,A和B都能够进入CLOSED状态; b) 防止已失效的连接请求报文段出现在本链接中。A在发送完最后一个确认报文段后,再经2MSL时间,就可以使本链接持续时间内所产生的所有报文段都从网络中消失,避免出现下一个新连接中出现该旧连接的连接请求报文段(在连接未完全关闭(即进入CLOSED状态)时,该方是无法建立一个新连接的)。 5) 除时间等待计时器外,TCP还有一个保活计时器,用于以下情况:客户已主动与服务器建立了TCP连接,但后来客户端的主机出了故障,服务器以后就无法再收到客户发来的数据,此时应有措施使服务器不用再白白等下去。设置了保活计时器后,服务器每收到一次客户的数据,便重新设置保活计时器,时间的设置通常是2小时;若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后每隔75分钟发送一次;若一连发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭该连接。 |