三次握手与四次挥手的实质就是客户端与服务器之间TCP建立通信的连接和断开的过程
三次握手:
三次握手目的:确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号并为后面的可靠性传送做准备。
第一次握手:客户端发送一个带有SYN=1的报文段给服务器,同时会初始序列号seq=x,此时客户端进入SYN_SENT状态。(这个数据包不能携带数据,但是会消耗一个序列号)
第二次握手:服务器在Listen状态下接收到客户端的SYN数据包后;若服务器同意建立连接,在确认报文段中把SYN和ACK都置位1,确认号ack=x+1;同时,服务器自己也会初始化序列号seq=y。此时服务器进入SYN_RCVD状态。(不能携带数据,消耗一个序列号)
第三次握手:客户端在接收到服务器的确认报文段后,还需要再向服务端发送一个确定报文段,会将ACK=1,确认序列号ack=y+1,这个报文段再发送给服务端,此时客户端就会进入ESTABLISHED状态(表示连接建立)。(再发送ACK报文段的时候,可以携带数据并消耗一个自己的序列号)。服务器接收到这个报文段后,也会进入ESTABLISHED状态。
以上就是三次握手的过程,连接建立之后就可以进行数据的交流了。
为什么要进行第三次握手?
原因一:
主要是为了防止已失效的连接请求报文段突然又传给了B,而产生错误。
情况一:A向B发送了一个连接请求报文,但因为某些原因导致报文丢失,收不到B的确认报文,于是A又会重新发送一次请求报文,之后收到的确认报文,连接建立。不会产生已失效的连接请求报文段
情况二:A向B发送了一个连接请求报文段,在网络中,并没有丢失,而是在某个网络节点滞留了,直到A与B连接释放后的某一个时间点才到达,此时B会以为是A又发送的一次连接请求,给A回复确认报文段后,B并不会理睬这个确认报文,因为没有第三次握手,所以B以为与A已经建立连接了,但是A却不以为然,一直不会发送数据,而造成B的资源浪费。
原因二:
1.如果只进行两次握手,只能保证客户端-->服务端建立连接成功,不能保证服务端与客户端的连接也建立了,因为服务端给客户端发的SYN+ACK客户端并没有回应
2.因为只有两次握手,只能确认服务端收发数据的能力是正常的,客户端只能确认其发送能力是正常的,不能保证它的接收能力是否正常。因为TCP需要保证可靠性,所以只能三次握手保证。
为什么不是四次握手?
四次握手的过程其实是将第二次握手分解为两步,服务端先回复了ACK确认报文,再发送一个SYN的请求报文。这样会增加额外的延迟和复杂性。
四次挥手
四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。
第一次挥手:A向B发出连接释放报文段,报文段首部的终止控制位FIN=1,序列号seq=u,发送后A变为FIN_WAIT_1状态。
第二次挥手:B收到连接释放报文段后会回复确认报文,报文段ACK=1,ack=u+1,seq=v。发送后B进入CLOSE_WAITE状态(半关闭状态)。这个状态下B仍可以向A发送数据。
A在收到B的确认报文后会进入FIN_WAIT_2状态。等待B发送连接释放报文
第三次挥手:B发送连接释放报文,FIN=1,seq=w,ack=u+1(重复上一次的确认号),ACK=1。此时B进入LAST_ACK状态。
第四次挥手:A收到B的连接释放报文后,会回复确认报文。确认报文中ACK=1,seq=u+1,ack=w+1。此时B进入TIME_WAIT状态。B在接收到确认报文后,进入CLOSED状态,连接关闭。
注:A在TIME_WAIT状态下需要等待2MSL(最长报文段寿命)时间才会进入CLOSED状态。
为啥要等待2MSL?
原因一:确保A的确认报文B能够收到,保证AB都能正常进入CLOSED状态。B在发送连接释放报文后,若收不到A的确认,就会重发一次连接释放报文,A在重传一次确认,会重新启动2MSL计时,B收到后才会进入CLOSED状态。若A不等待2MSL而是直接进入CLOSED,那么A收不到B重传SYN+ACK,B也无法收到A的确认,则会导致B无法进入CLOSED状态。
原因二:防止类似“已失效连接请求报文段”情况的发生。等待2MSL可以保证在本次连接的时间内,产生的所有报文段都从网络中消失了,不会使下一个新连接出现旧的报文段。