在计算机网络中,TCP的连接的建立和断开过程即三次握手和四次挥手是相当重要的。本人在面试的时候,就经常会被面试官问到这方面的知识,一开始虽然自己心里是知道但表达出来还是磕磕碰碰的,相当坎坷,但这可能会导致面试官会产生一种觉得你对这块的知识并不是很熟悉的“错觉”。所以把基础的知识掌握并明确的表达出来很重要,本人血的教训QAQ。
所以,今天就将TCP的三次握手和四次挥手过程做详细整理,并附上面试过程中常被问到的问题及其答案,以便后续复习和大家参考。
在计算机网络体系结构中,TCP是作用在运输层的一个面向连接的协议。所以TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。
一、TCP连接的建立的释放过程
1、TCP连接的建立(三次握手)
TCP建立采用客户服务器方式,主动发起连接建立的应用进程叫做客户端,被动等待连接的叫做服务器。TCP连接的的过程叫做握手,握手需要在客户和服务器之间交换三个TCP报文段,其实大家口中流传的三次握手并不是进行了三次握手,而是一次握手过程中交换了三个报文,准确的描述应该是“三报文握手”即“three way (three message) handshake”。
下图给出了具体过程:
注意:TCP规定,SYN报文段不能携带数据但要消掉一个序号;
TCP规定,ACK报文段可以携带数据,但如果不携带数据则不消耗序号。上图中客户端给服务器发送的确认报文段中就没有携带数据,此时序列号仍为x+1。
2、TCP连接的释放(四次挥手)
数据传输结束后,通信的双方都可释放连接,下图给除了连接断开的具体过程(假设主动断开方是客户端)
时间MSL叫做最长报文段寿命,是一个报文段在网络中的最大生存时间 ,而TIME-WAIT状态需要等待2MSL的时间,具体原因下方有解释。
半关闭状态:TCP从一端到另一端单向连接关闭,即数据不能以这个方向传送。
二、面试常见问题
1、为什么是三报文握手而不是二或者四呢?
(1)为什么不是两次?(相较于后者重要)
为了防止已失效的连接请求报文段突然又传送到了B端,而产生错误。
所谓“已失效的连接请求报文段”是这样产生的。考虑一种正常情况,A发出连接请求,但因请求连接报文丢失而未收到确认,于是A重传一次连接请求,B收到了确认,建立了连接,数据传输完后释放了连接。A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B,没有“已失效的连接请求报文段”。
现在假定一种异常情况,即A发出的第一个连接请求报文段并未丢失,只是在某些网络节点长时间滞留了,以致延误到连接释放以后才到达B,这时B收到后会误以为A又发出了一个新的连接请求,于是向A发送确认报文段,同意建立连接,这时如果没有第三个报文的话,只要B发出确认,新的连接就建立了。
但显然此时A并未发出连接建立的请求,因此不会理睬B的确认,也不会向B发送数据,但B却以为新的链接已经建立并在等待A发来数据,B的许多资源就这样被白白浪费。
显然这是不合理的。
(2)为什么不是四次?
TCP是全双工的通信方式,它在建立连接的过程中直接就把两步合成 了一步,即当client端给server端发送SYN请求后,server端直接将对这个SYN请求的ACK和自己的SYN请求合并在一起发过去了,从而节约了一次,当然也可以将其分开,但显然合并在一起发过去更加节省资源。
2、四次挥手,三次挥手可不可以?
可以,当服务器将FIN和ACK在同一报文中发送,即同时发送FIN和ACK(图中第2条线和第3条线合并)也是可以的。
四次挥手是因为TCP是全双工的通信方式,即一方断开连接后,不能向另一方发送数据,但是此时另一方可以向自己发送数据,双方断开连接是独立的。服务器端在收到客户端的FIN报文后会立即发送确认ACK报文,再通知应用层来决定Server端到Client端的单向连接是否要关闭,如果应用层没数据要发则服务端此时再发一个FIN,这就导致比TCP建立多了一步,此时FIN和ACK不是在同一报文中发送。
3、四次挥手中,为什么在TIME-WAIT状态时主动断开方必须等待2MSL的时间?
(1)为了保证A发送的最后一个ACK确认报文段能够到达B。
这个ACK报文段有可能会丢失,因而是处在LAST-ACK状态的B收不到连接关闭的确认报文段,B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK。接着A重传一次确认ACK,重新启动2MSL计时器,最后A和B都正常进入了CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK后立即释放链接,那么就无法收到B重传的FIN+ACK,因而不会再重新发送一次ACK,这样,B就无法按照正常步骤进入CLOSED状态。
(2)防止上面提到的“已失效的连接请求报文段”出现在本连接中。
A发送完最后一个确认报文段ACK后,在经过2MSL时间(MSL:最长报文段寿命),就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
B只要收到了A发出的确认,就进入CLOSED状态。同样B在撤销相应的传输控制块TCB后,就结束了这次的TCP连接。可以注意到,B(被动断开方)比A(主动断开方)更早进入CLOSED状态。
4、TIME-WAIT状态存在的意义
(1)保证迟来的数据能被识别并丢弃,防止对后续新的链接造成影响
经过TIME-WAIT状态,上一次连接中所有的包都会消失。
(2)保证可靠的终止TCP连接
主动关闭方发送的最后一个ACK 有可能丢失,这时被动方会重新发FIN, 但如果主动断开方没有TIME-WAIT状态而立即进入CLOSED状态时,被动断开方没有收到确认关闭的ACK,会一直重传FIN,而导致无法正常进入CLOSED状态。