TCP三次握手、四次挥手
TCP三次握手
TCP的连接建立,我们常常称为三次握手。
A:您好,我是A
B:您好A, 我是B
A:您好B
我们也称之为“请求->应答->应答之应答”
1、一开始,客户端和服务器都处于CLOSED状态。
2、先是服务端主动监听某个端口,处于LISTEN状态。
3、然后客户端主动发起连接SYN,之后处于SYN-SENT状态。
4、服务器收到发起的连接,返回SYN,并且ACK客户端的SYN,之后处于SYN-RCVD状态。
5、客户端收到服务器发送的SYN和ACK之后,发送ACK的ACK,之后处于ESTABLISHED状态。
6、服务器收到ACK的ACK之后,也处于ESTABLISHED状态。这样就可以进行数据传输了。
为什么要三次,而不是两次?而且为了可靠,为什么不是四次?
我们假设这个通路是非常不可靠的,A发起一个请求连接,这个连接并没有丢失,只是在网络中滞留的时间太长了,由于客户端没有收到确认报文,就会以为服务器没有收到,此时就会重新向服务器发送请求,至此,客户端和服务器两次握手完成连接。
但在此之前还在滞留了一个请求,这个请求连接现在到达服务器,就会让客户端和服务器再次建立连接,这个请求报文本该是失效的,这将导致不必要的错误的资源浪费。
如果四次,那么就造成了浪费,因为在三次结束之后,就已经可以保证A可以给B发信息,A可以收到B的信息; B可以给A发信息,B可以收到A的信息。
TCP四次挥手
A:B啊,我不想玩了
B:哦,你不想玩了呀,我知道了
B:A啊,那我也不玩了,拜拜
A:好的,拜拜
1、当A说“B啊,我不想玩了”,就进入了FIN-WAIT-1的状态。
2、B收到“A不玩”的消息后,发送“我知道了”,就进入CLOSED-WAIT状态。
3、A收到B说“我知道了”就进入了FIN-WAIT-2的状态,如果这个时候B直接退出,那么A将永远在这个状态。
4、如果B没有退出,发送了“那我也不玩了”的请求到达A时,A就发送知道B也不玩了的ACK,并且从FIN-WAIT-2状态结束。
5、按理说,这个时候A就可以直接退出了,但是最后的这个ACK万一B收不到呢,那么B就会重新发一个“B不玩了”,这个时候如果A已经退出的话,B就再也收不到ACK了,因而TCP协议要求A最后等待TIME-WAIT的时间,这个时间要足够长,长到如果B没收到ACK的话,B重新发送“B说不玩了”,A会重新发一个ACK并且有足够时间到达B。
等待的时间设为2MSL,MSL是Maximum Segment Lifetime,报文的最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
有一种异常情况就是,B超过了2MSL的时间还没有收到A发来的FIN的ACK确认,这时,按照TCP的原理,B就会重新发送FIN,这个时候A再收到这个包时,就会认为,我在这已经等了这么久了,之后的我就不管了,于是就直接发送RST,B就知道A已经退出了。
为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,自己也未必全部数据都发送给对方了,所以自己可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,自己的ACK和FIN一般都会分开发送。