【3分钟带你学】TCP/IP三次握手和四次挥手

TCP/IP三次握手和四次挥手

三次握手


我们经常在微信或QQ上和别人聊天,

【3分钟带你学】TCP/IP三次握手和四次挥手

​ 我们正常的聊天是这样的,网络通信也是如此,我们把每次发送的消息都叫做是一次握手,上面这个例子就是二次握手,建立了通信连接,接下来就可发送继续发送信息了。

​ 但是二次握手有个问题,首先信息是通过信道(信息通道)进行传递的,但是信道并不可靠,如果网络由于网络原因,A的“在吗”这个消息被阻塞在某个节点,(这里可以脑补下,双十一买的东西,堵在路上了),然后这个阻塞的时间很长,(超出了设定的超时重发时间),A得不到B的回应,那么A就会认为这个消息丢失了,然后重新发送“在吗”。如下图:

【3分钟带你学】TCP/IP三次握手和四次挥手

​ 这次B收到这个消息,并回复“在的,你说”,然后A开始和B交流通信(吧啦吧啦说一堆),当通信结束后,那个之前被认为丢失了的消息到达了B,此时对于B而言,以为又是一个新的消息,就又给A发送了一个确认消息“在的,你说”。但是此时对于A而言,A会想:说,说你妹啊。它认为它没有给B再次发送消息,所以就不会理睬这条确认消息。但是B还在傻傻地等待着A的消息。。。。。这就很尴尬了,浪费了很多时间,时间就是生命啊!(对于服务器而言,就是CPU等资源的浪费)。为了解决这个问题就有TCP第三次握手。

【3分钟带你学】TCP/IP三次握手和四次挥手

A在收到B的确认消息后,又给B发了确认消息,这样经过了三次握手,客户端和服务器端都有应有答,这样就可以确保了TCP通信的正确连接。这就是TCP三次握手。

原理就是这样,而计算机如何具体实现呢?

计算机实现


第一次握手
当客户端向服务器发起连接请求时,客户端会发送同步序列标号SYN到服务器,在这里我们设SYN为m,等待服务器确认,这时客户端的状态为SYN_SENT

第二次握手
当服务器收到客户端发送的SYN(m)后,服务器要做的是确认客户端发送过来的SYN,在这里服务器发送确认包ACK,这里的ACK为m+1,意思是说“我收到了你发送的SYN了”,同时,服务器也会向客户端发送一个SYN包,这里我们设SYN为n。这时服务器的状态为SYN_RECV
一句话,服务器端发送SYN和ACK两个包

第三次握手
客户端收到服务器发送的SYN(n)和ACK(m+1)包后,知道了之前的同步***m数据已经发送成功了,客户端状态变为ESTABLISH,需向服务器发送确认包ACK,“我也收到你发送的SYN了,我这就给你发个确认过去,然后我们就能开始通信了”,这里的ACK为n+1,服务器端接收到ACK后,服务器的状态变为ESTABLISH,即TCP连接成功。

【3分钟带你学】TCP/IP三次握手和四次挥手

在三次握手中,客户端和服务器端都发送两个包SYN和ACK,只不过服务器端的两个包是一次性发过来的,客户端的两个包是分两次发送的。

有童鞋会说,如果A发给B的确认丢了,该如何

A会超时重传这个ACK吗?不会!TCP不会为没有数据的ACK超时重传。那该如何是好?B如果没有收到A的ACK,会超时重传自己的SYN同步信号,一直到收到A的ACK为止。

补充阅读:

第一个包,即A发给B的SYN 中途被丢,没有到达B

A会周期性超时重传,直到收到B的确认

第二个包,即B发给A的SYN +ACK 中途被丢,没有到达A

B会周期性超时重传,直到收到A的确认

第三个包,即A发给B的ACK 中途被丢,没有到达B

A发完ACK,单方面认为TCP为 Established状态,而B显然认为TCP为closed状态:

a. 假定此时双方都没有数据发送,B会周期性超时重传,直到收到A的确认,收到之后B的TCP 连接也为 Established状态,双向可以发包。

b. 假定此时A有数据发送,B收到A的 Data + ACK,自然会切换为established 状态,并接受A的 Data。

c. 假定B有数据发送,数据发送不了,会一直周期性超时重传SYN + ACK,直到收到A的确认才可以发送数据。

四次挥手


当A端和B端要断开连接时,需要四次握手,这里称为四次挥手

断开连接请求可以由客户端发出,也可以由服务器端发出,在这里我们称A端向B端请求断开连接。

第一次挥手

A端向B端请求断开连接时会向B端发送一个带有FIN标记的报文段,这里的FIN是FINSH的意思。

第二次挥手

B端收到A发送的FIN后,B段现在可能现在还有数据没有传完,所以B端并不会马上向A端发送FIN,而是先发送一个确认序号ACK,意思是说“你发的断开连接请求我收到了,但是我现在还有数据没有发完,请稍等一下呗”。

第三次挥手

当B端的事情忙完了,那么此时B端就可以断开连接了,此时B端向A端发送FIN序号,意思是这次可以断开连接了。

第四次挥手

A端收到B端发送的FIN后,会向B端发送确认ACK,然后经过两个MSL时长后断开连接。

MSL是Maximum Segment Lifetime,最大报文段生存时间,2个MSL是报文段发送和接收的最长时间。

【3分钟带你学】TCP/IP三次握手和四次挥手

为什么TCP连接是三次,挥手却是四次?

在TCP连接中,服务器端的SYN和ACK向客户端发送是一次性发送的,而在断开连接的过程中,B端向A端发送的ACK和FIN是是分两次发送的。因为在B端接收到A端的FIN后,B端可能还有数据要传输,所以先发送ACK,等B端处理完自己的事情后就可以发送FIN断开连接了。

为什么在第四次挥手后会有2个MSL的延时?

前文说到MSL是Maximum Segment Lifetime,最大报文段生存时间,2个MSL是报文段发送和接收的最长时间。假定网络不可靠,那么第四次发送的ACK可能丢失,即B端无法收到这个ACK,如果B端收不到这个确认ACK,B端会定时向A端重复发送FIN,直到B端收到A的确认ACK。所以这个2MSL就是用来处理这个可能丢失的ACK的。


本文参考:
TCP的三次握手和四次挥手
TCP 为什么是三次握手,为什么不是两次或四次?
《计算机网络》第四版