0%

三次握手和四次挥手

模拟过程

A:听得到吗?

B:听得到,你呢?(B在回复的时候,说明A发送信息没问题,B接收信息没问题)

A:听得到。(A在回复的时候,说明B发送信息没问题,A接收信息没问题)

。。。

。。。

。。。

A:我要闭嘴了,确认请挥手。

B:🙋‍♂️。(B这里挥手示意收到A消息,说明A发送信息没问题,B接收信息没问题)

B:我也要闭嘴了,确认请挥手。(这里B回复A,跟B挥手示意不是一次进行,是因为在B在收到A消息的时候,可能手上的事情还没做完,等做完了再回复)

A:🙋‍♂️。(这里A挥手,说明B发送信息没问题,A接收信息没问题)

科普

TCP 协议通过三次握手的形式建立一个可靠的连接,建立成功之后开始发送数据。发送数据完了之后,会以四次挥手的形式来终止连接。

一、描述一下 TCP 连接三次握手的过程?

  • 第一次握手:客户端尝试连接服务器,向服务器发送 SYN (Synchronization 的缩写)包,并且设置一个序列号 seq(Sequence 的缩写),假设 seq=m;发送完成之后,客户端进入 SYN_SEND 状态等待服务器确认;

  • 第二次握手:服务端接收客户端 syn 包,做出回应;服务端会回送 SYN 和 ACK 给客户端。ACK 的全写是 acknowledgment ,意为答复,ACK 的值是根据客户端发送过来的 seq 来决定的,发给给客户端时,ACK 的值是根据客户端发送的 syn=m 来确认的(假设在 m 的基础上 +1),这样客户端收到回应的时候就能准确知道是服务端的回应了;服务端回应里里的 seq = n 是服务端自己生成的,给客户端进行回应使用的。发送完成之后,服务器进入 SYN_RCVD 状态;

  • 第三次握手:客户端收到服务端的 SYN+ACK 包,向服务端发送确认包 ACK(ack=n+1,根据刚刚收到的服务端发送的 seq = n 确定的),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,表示连接成功,完成三次握手,这个时候就可以传输数据了。

img

二、为什么握手需要三次,两次不行吗?

三次握手的目的是为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

“已失效的连接请求报文段”的产生在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。—— 谢希仁版《计算机网络》

三、描述一下四次挥手的过程?

  • 第一次挥手(FIN=1,seq=x):假设客户端想要关闭连接,客户端发送一个 FIN (Finish 的缩写,表示结束)标志位 置为 1 的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入 FIN_WAIT_1 状态。

  • 第二次挥手(ACK=1,ACKnum=x+1):服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。

  • 第三次挥手(FIN=1,seq=y):服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为 1。发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。

  • 第四次挥手(ACK=1,ACKnum=y+1):客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。

  • 最后,客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。

img

四、为什么挥手需要四次,三次不行吗?

握手的时候,客户端和服务端打个招呼,服务端可以直接把自己的 SYN 信息和对客户端的回应 ACK 信息一起带上,但是挥手的时候,客户端说我要断开了,服务端还没发完最后的数据,因此需要先回应一下客户端:我收到你的断开的请求了,但是你要等我把最后的内容给你,所以这里分开了 2 步:

  • 回应客户端;
  • 发送自己的最后一个数据。

五、为什么四次挥手里,客户端进入 TIME_WAIT 状态后,需要等待最大报文段生存的时间后,才能关闭?

客户端在发送完 ACK 报文段后,再经过 2MSL 时间,就可以使连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段。