轻松理解tcp的三次握手、四次挥手
介绍:tcp是面向连接的协议,运输连接是用来传送tcp报文的,所以每次连接都有三个过程:建立连接、数据传送、连接释放。
tcp连接建立过程中要解决一下三个问题:
(1)要使每一方知道对方的存在
(2)要允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项等)
(3)能够对运输实体资源(如缓存大小、连接表中的项目)进行分配
1.tcp的连接建立(三次握手)
先上图:
(1)最初客户端A和服务器端B都处于CLOSED(关闭)状态,客户端A开始向服务器B发出连接请求,客户端主动打开连接,服务器B被动打开连接,进入LESTEN(收听)状态。
(2)A的tcp客户进程首先创建传输控制块(TCB),然后向服务器B发送连接请求报文段,这时首部同部位SYN=1,选择一个初始序号seq=x,规定该报文段不携带数据,但要消耗掉一个序号,此时客户端进入SYN-SENT(同步已发送)状态。(一次握手)
(3)服务器B收到连接请求报文段,同意建立连接,并向客户端A发送确认。在确认报文段中把SYN=1,ACK=1,确认号ack=x+1,同时也为自己选择一个初始***seq=y,这个报文段也不携带数据,仍要消耗一个序号,这时服务器进入SYN-RECD(同步收到)状态。(二次握手)
(4)客户端收到服务器B的确认后,还得向B确认,确认报文段的ACK=1,确认号ack=y+1,规定ACK报文段可以携带数据,如果不携带则不消耗序号。这时tcp连接建立,客户端A进入ESTABLISHED(已建立连接)状态。当服务器B收到客户端A的确认后,也进入ESTABLISHED状态。(三次握手)
注意:为什么客户端A最后还要发送一次确认呢?
----主要是为了防止已失效的连接请求报文段(一次握手的连接请求)突然又传送到了服务器B,因而产生错误。
----假如没有第三次握手的确认,客户端A发送的连接请求由于网络延迟滞留了,于是A就再次重传一次连接请求,这次连接成功,并且顺利传输信息后就断开连接了,但这之后客户端A第一次连接请求由于网络变通畅到达了服务器B,B就答应连接,然后B就开始等待客户端A发送信息,但是这是A之前发的请求,并且也交互完成了,现在A没有请求连接,但服务器B不知道,所以一直等待A发来数据。这样B的许多资源就白白浪费了。
----采用三次握手了,客户端A不会向服务器B发出确认,B没收到确认,就知道了A并没有请求建立连接。
2.tcp的连接释放(四次挥手)
还是先上图:
(1)数据传输结束后,通信的双方都可以释放连接。现在客户端A和服务器B都处于ESTABLISHED状态。A的应用进程先向其tcp发出连接释放报文段,并停止发送数据,主动关闭tcp连接。A把连接释放报文段首部的终止控制位FIN=1,序号seq=u,等于前面已传过来的数据的最后一个字节的序号加1。FIN报文段即使不携带数据,也消耗一个序号。此时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。(一次挥手)
(2)服务器B收到连接释放报文段后即发出确认,确认号ack=u+1,seq=v,ack=u+1,B进入CLOSE-WAIT(关闭等待)状态。tcp服务器进程通知上面应用层进程,A到B的连接已经释放了。此时tcp处于半关闭状态。A没有数据传输了,但要是B有数据发送,A还是要接收的。(二次挥手)
(3)A收到B的确认后,进入FIN-WAIT-2(终止等待2)状态,等待B发出连接释放报文段。B没有数据发送了,通知应用进程释放连接,B发送到连接释放报文段FIN=1,ACK=1,seq=w,ack=u+1。此时B进入LAST-ACK(最后确认)状态,等待A确认。(三次挥手)
(4)A收到B的连接释放报文段后,必须对此发出确认。且ACK=1,ack=w+1,seq=u+1,,然后进入到TIME-WAIT(时间等待)状态。此时tcp连接还没有释放。必须经过时间等待计时器设置的2MSL(Maxinum Segment Lifetime 最长报文段寿命)后,才进入CLOSED状态。(四次挥手)
注:为什么A在TIME-WAIT状态必须等待2MSL的时间?有两个理由
第一,保证A最后发送的确认报文段发送给B,这个ACK报文段可能会丢失,B就会超时重传FIN+ACK报文段,A就再一次确认。2MSL后B没有反应,就都进入CLOSED状态,如果A不等就释放连接,B可能没收到确认,就进入不了CLOSED状态。其实这个时间应该大于2MSL,因为A、B确认等操作可能会花一部分时间。
第二,防止失效的请求报文段出现在本次连接中,经过2MSL,可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样可以使下次新的连接中不会出现这种旧的连接请求报文段。
最后我们注意到,B结束tcp连接的时间要比A早一些(可能是一个MSL)。