从另一个视角理解TCP握手、挥手与可靠传输
本文将深入探讨 TCP 协议中三次握手、四次挥手的原理,以及其保证可靠传输的机制。
一、三次握手:为何是三次,而非两次?
建立 TCP 连接的过程犹如一场严谨的 “对话”,需要经过三次握手才能确保通信双方的可靠连接。
三次握手的具体流程
第一次握手:客户端率先向服务端发送带有 SYN(SEQ=x)标志的数据包,随后进入 SYN_SEND 状态,此时客户端如同一位等待回应的信使,它不清楚服务端的任何状况。而服务端接收到该数据包后,确认了客户端具备发送能力,同时也确认自身接收功能正常。
第二次握手:服务端回应客户端,发送带有 SYN + ACK (SEQ=y, ACK=x + 1) 标志的数据包,进入 SYN_RECV 状态。客户端接收到此数据包后,不仅确认自己的发送和接收功能正常,还确认了服务端的发送和接收同样正常。
第三次握手:客户端再次向服务端发送带有 ACK (ACK=y + 1) 标志的数据包,随后客户端和服务端双双进入 ESTABLISHED 状态,至此三次握手完成,双方可以开启数据传输之旅。此时,双方都明确彼此的发送和接收功能均处于正常状态。
两次握手的缺陷
网络环境复杂多变,丢包问题时有发生。若仅进行两次握手,当第二次握手时服务端发给客户端的确认报文丢失,就会出现严重问题。此时,服务端认为连接已建立并准备接收和处理数据,而客户端由于未收到确认报文,不会发送数据,并且会忽略服务端后续的数据。然而,若采用三次握手,即便客户端发送的确认报文丢失,服务端在一段时间内未接收到,就会重新发起第二次握手,从而保障连接建立的可靠性。
二、四次挥手:为什么断开连接需要4次?
当数据传输任务完成,TCP 连接的断开同样需要遵循严谨的流程,即四次挥手。
四次挥手的详细步骤
第一次挥手:客户端向服务端发送带有 FIN(SEQ=x)标志的数据包,表明客户端到服务端的数据传送即将结束,随后客户端进入 FIN - WAIT - 1 状态。这就像是客户端告知服务端:“我这边的数据已经发送完毕啦”。
第二次挥手:服务端收到客户端的 FIN 数据包后,向客户端发送 ACK (ACK=x + 1)标志的数据包,确认收到客户端的断开请求,服务端进入 CLOSE - WAIT 状态,客户端则进入 FIN - WAIT - 2 状态。此时,服务端可能还有数据需要继续发送。
第三次挥手:当服务端完成剩余数据的发送后,向客户端发送 FIN (SEQ=y) 标志的数据包,请求关闭连接,自身进入 LAST - ACK 状态。这一步相当于服务端回应客户端:“我这边的数据也发完了,我们可以断开连接了”。
第四次挥手:客户端收到服务端的 FIN 数据包后,发送 ACK (ACK=y + 1) 标志的数据包给服务端,然后进入 TIME - WAIT 状态。服务端收到 ACK 数据包后进入 CLOSE 状态。客户端在 TIME - WAIT 状态等待 2MSL(最长报文段寿命)后,如果没有收到其他回复,就可以确认服务端已正常关闭,随后客户端也关闭连接。在四次挥手未完成之前,客户端和服务端仍可继续传输数据。
为什么一定是四次挥手?
TCP 采用全双工通信模式,允许数据在两个方向上同时传输。因此,任何一方都可以在数据传送结束后发起连接释放的通知,待对方确认后进入半关闭状态。只有当双方都完成数据传输并确认后,才能完全关闭 TCP 连接。至于为何不能将服务端发送的 ACK 和 FIN 合并为一次,变成三次挥手,原因在于服务端收到客户端断开连接的请求时,可能还有一些数据尚未发送完毕。此时先回复 ACK,表示已接收到断开连接的请求,等到数据发送完成后再发送 FIN,以断开服务端到客户端的数据传送。
三、TCP 如何确保可靠传输?
为了保障数据在网络中的可靠传输,TCP 采用了一系列精妙的机制。
基于数据块传输
TCP 会将应用数据分割成其认为最适宜发送的数据块(报文),再传递给网络层。这就好比将一大箱货物合理地分装成多个小包裹,以便在复杂的网络道路上高效运输,提高传输效率。
数据包的排序与去重
TCP 为每个数据包分配一个唯一的序列号,如同给每个小包裹贴上特定的标签。接收端依据这些序列号对接收到的数据进行排序,并去除重复序列号的数据,从而确保数据的准确性和有序性。
校验和机制
TCP 会计算并维护首部和数据的检验和,这就像是给每个包裹贴上一个质量检测标签。若接收到的报文段检验和出现差错,TCP 会果断丢弃该报文段,并且不确认收到此报文段,以此保证数据的完整性。
重传机制
基于计时器的重传(超时重传):数据包发送出去后,TCP 会启动一个计时器。若在规定时间内未收到对方的确认应答(ACK),就如同包裹寄出后长时间没有收到收件人的确认,TCP 会重新发送该数据包。
快速重传:当接收端发现数据包失序时,会立即向发送端发送重复的 ACK 报文。发送端在收到多个重复的 ACK 后,无需等待计时器超时,就会迅速重传丢失的数据包,大大提高了重传的效率。
SACK(选择性确认):在快速重传的基础上,接收端会返回最近收到的报文段的序列号范围,这样发送端就能清楚地知道哪些数据包已经成功到达服务器,从而精准地重传丢失的数据。
D - SACK(重复 SACK):D - SACK 在 SACK 的基础上更进一步,额外携带信息告知发送方哪些数据包被重复接收了,帮助发送方更全面地了解网络状况,优化重传策略。
流量控制
TCP 连接的双方都设有固定大小的缓冲空间。接收端通过滑动窗口协议,如同调节一扇窗户的开合程度,只允许发送端发送接收端缓冲区能够接纳的数据量,以此防止数据拥堵,避免数据包丢失。
拥塞控制
TCP 在发送数据时,会充分考虑两个关键因素:接收方的接收能力和网络的拥塞程度。接收方的接收能力通过滑动窗口来体现,表示接收方还有多少缓冲区可用于接收数据;网络的拥塞程度则由拥塞窗口表示,这是发送方根据网络状况自行维护的一个值,反映了发送方认为可以在网络中顺利传输的数据量。发送方发送数据的大小取滑动窗口和拥塞窗口的最小值,这样既能确保不超过接收方的接收能力,又能避免对网络造成过度拥塞。
资料:计算机网络面试必备知识点详解-CSDN博客