快速理解TCP三次握手和四次挥手原理
TCP三次握手原理:
原理图如下:
TCP三次握手的过程:
1)客户端A主动打开连接,服务器B被动打开连接。B建立传输控制块TCB 并且有CLOSED 状态变成 LISTEN 状态,等待A发送连接请求。
2)第一次握手: A 建立传输控制块TCB ,然后将向服务器B 发送连接请求报文,将报文中TCP首部的SYN(同步位) 置 ‘1‘ ,并且随机选择一个初始序号seq 。发送完报文后,客户端A 由CLOSED 状态变成 SYN-SENT(同步已发送) 状态
3)第二次握手: 服务器B收到A的连接请求后,如果同意建立连接,则向A发送报文,表示收到请求报文并且同意。并且将报文中 ACK(确认位) 置 ’1‘,SYN(同步位) 置 ‘1‘ ,确认号(ack) = x+1 ,并且选择一个初始序号seq=y。发送完报文后,服务器B由LISTEN 状态变成 SYN-RCVD(同步收到) 状态
4)第三次握手: 客户端A收到服务器B的确认后,还要再一次向B给发送确定报文。报文 ACK=1,seq=x+1,ack=y+1。发送报文之后TCP正式建立。 客户端A和服务器B变成 ESTAB-LISHED(已建立连接) 状态
常见问题:为什么要握手三次?两次会有什么问题?
考虑如下这种情况(握手两次为前提下):
- A(客户端)向B(服务器)发送连接请求,但是这个请求因为某种原因在网络中滞留了很久,直到客户端A已经释放这个请求之后,B才收到这个滞留的连接请求。
- B同意建立连接,向A发送报文。此时连接建立,并且等待A发送信息报文。
- 此时由于A并没有发出新的连接请求,所以A对B的同意报文不予理睬,也不会向B发送数据报文。但是B认为已经和A建立了连接,所以会一直等待A发送信息。这样就会浪费B的很多资源和时间。
所以:为了解决以上出现的问题,采用三次握手的办法。最后A向B发送一次报文,在上面的例子中,A不会向B的确认发出确认,B收到确认,就不会建立连接。
TCP四次挥手原理:
原理图如下:
TCP四次挥手的过程:
1) 第一次挥手: A向B发送连接释放报文,将FIN(终止位) 置1,并且选择一个序号seq=u ,A进入FIN WAIT-1(终止等待1) 状态
2) 第二次挥手: B收到连接释放报文,发送确认报文,确认连接释放报文收到,报文中ACK=1,seq=v,ack=u+1,A进入FIN-WAIT-2(终止等待2) 状态,B进入 CLOCK-WAIT(关闭等待) 状态,A→B 方向的连接关闭,B→A方向的连接没关闭,此时B处于半关闭状态。
3) 第三次挥手: 等待B处理完后,B向A发送连接释放报文,其中报文FIN=1,ACK=1,seq=w,ack=u+1,B进入LAST-ACK(最后确认)状态
4) 第四次挥手: A收到连接释放报文,发送确认报文,其中ACK=1,seq=u+1,ack=w+1; 然后A进入TIME-WAIT(时间等待)状态,B进入CLOSED状态
5) 最后: A在经过时间等待计时器设定的时间后(这里是2MSL),也进入CLOSED状态,当TCB传输块撤销后,连接完全断开
第三次挥手的必要性:
在第二次挥手的时候,A→B 方向的连接关闭,A不再向B发送数据。但是B可能还要处理一些事务,可能还要向A发送数据。所以当B处理完事务之后,再向A发送连接释发报文(第三次挥手)。
为什么要A最后要等待2MSL?
1)最后一个ACK确认报文可能会丢失,处于最后确认状态的B收不到确认报文会超时重传第二挥手和第三次挥手的报文。A也会重新发送ACK确认报文并且也会重启2MSL计时器,有点循环等待结束的味道。
2)设置2MSL可以使本次连接中的所有相关报文从网络中清除,保证下次连接不会出现旧连接请求报文
保活计时器的作用:
TCP中还有个保活计时器,用来防止客户端故障,服务器持续等待。服务器每接收一次客户端的数据就会重新设置保活计时器,当再设定之间内,服务器没有收到数据,就会每隔75s向客户端发送一次探测报文段,十次之后还是没有收到数据,就会断开这次连接
总结:
三次握手:A请求建立连接——B同意建立连接——A收到B同意,AB正式建立TCP连接
四次挥手:A请求关闭连接——B收到关闭请求,请等待B处理完事务——B处理完事务,请A确认是否关闭——A确认关闭——B进入CLOSED,等待一下后A进去CLOSED