图解TCP协议中的三次握手和四次挥手,一个同同事互水的技术话题(经典面试题目)

1.前言

通常,建立TCP需要三次握手才能建立,而断开连接则需要四次握手

然而,昨晚同事就这个问题抛出了自己的疑问点:

  • 建立TCP,为什么不能两次握手呢?
  • 为什么三次握手就有保证呢?是不是可能需要四次握手呢?

因此,记录一下笔记。我们的讨论内容涉及到:

  • 网络链路重传、网络链路延迟
  • 服务端资源消耗
  • 网络攻击、网络

2. TCP经典通信状态流转

首先,来一张经典图片:
在这里插入图片描述

2.1 Client状态经历过程

从client(客户端)来看,状态机包括6种状态,分别为:

  • Closed
  • SYN-SEND
  • ESTABLISED
  • FIN-WAIT-1
  • FIN-WAIT-2
  • TIME-WAIT

在这里插入图片描述

2.2 Server状态经历过程

从Server(服务端)来看,状态机包括6种状态,分别为:

  • Closed
  • LISTEN
  • SYN_RCVD
  • ESTABLISED
  • CLOSE_WAIT
  • LAST_ACK

在这里插入图片描述

3.TCP通信过程

在了解阶段过程之前,先看看TCP报文。

3.1 TCP报文

在这里插入图片描述
比较重要的字段有:
1.序号(sequence number):占4个字节,指本报文段所发送的数据的第一个字节的序号。

2.确认号(acknowledgement number):同样占4个字节,是期望收到对方下一个报文段的第一个字节的序号。(即收到对方的报文段最后一个字节的序号加一)(序号和确认号是TCP可靠传输的关键部分

3.(部分)标志位(Flags)

  • 确认(ACK):只有标志位ACK=1时确认号字段(acknowledgement number)才有效;(注意区分 确认号ACK 和 标志位 ACK
  • 同步(SYN):SYN=1表示这是一个“连接请求(SYN)”或“连接接受(SYN-ACK)”报文;
  • 终止(FIN):用于释放连接,FIN=1表明报文段发送完毕,要求释放连接。

4.窗口:占2字节,窗口大小最大为65535,是用来让对方设置发送窗口的依据。滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制

3.2 TCP通信三阶段

参考文献:

整个TCP通信可以分为三个阶段:

  • 建立连接阶段(三次握手Hello)
  • 数据传输阶段(多次传输数据,不是本次重点)
  • 断开释放连接阶段(四次挥手拜拜)

3.2.1 建立连接阶段(三次握手Hello)

所谓的三次握手,其实就是TCP连接的建立过程。

在这里插入图片描述
这里可以简单概括为影响了三个状态(不管是客户端还是服务器):

  • CLOSED(简称C)
  • SYN(简称S)
  • ESTABLISHED(简称E)

这里以一个业务场景来讲述握手协议:

  • 单片机菜鸟哥现场解答众粉丝技术问题(鸟哥作为服务端,众粉丝作为众客户端)
3.2.1.1 第一次握手 ——你好,我是你的粉丝张三,很高兴认识你

握手流向客户端 ——>服务端

场景说明

  • 你好,我是你的粉丝张三,很高兴认识你

协议说明

  • 客户端主动往服务端发起SYN(Seq = X)的报文,表示 请求建立新连接,随后进入 SYN 状态(从 CLOSED状态切换到SYN状态

在这里插入图片描述

3.2.1.2 第二次握手 ——你好,我是单片机菜鸟哥,很高兴认识你+1

握手流向客户端 <——服务端

场景说明

  • 你好,我是单片机菜鸟哥,很高兴认识你+1

协议说明

  • 服务端在 LISTEN 状态下收到客户端的SYN报文后,会给客户端返回响应应答 SYN +ACKSeq = Y,Ack = x +1,表示收到客户端的Seq号),随后进入 SYN 状态(服务端从LISTEN状态下切换到SYN状态

在这里插入图片描述

3.2.1.3 第三次握手 ——很好,我们可以开始技术交流了

握手流向客户端 ——>服务端

场景说明

  • 很好,我们可以开始技术交流了,这个时候鸟哥就可以开始进入粉丝答疑环节。

协议说明

  • 客户端收到 SYN+ACK 包之后,回复给服务端一个ACKSeq = x+1,Ack = y + 1,Ack等于服务端Seq +1,表示收到服务端的Ack),然后进入到 ESTABLISHED 状态
  • 服务端收到 ACK 包之后,知道客户端收到了自己的应答,也进入到 ESTABLISHED 状态
  • 双方开始正常通信

在这里插入图片描述
整个过程都是在计算Ack和Seq的值,保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续"握手",以此确保了"三次握手"的顺利完成。

这里引用一个动态图:
在这里插入图片描述

这就是 “三次握手”的过程。

粉丝A:你好,我是你的粉丝A,很高兴认识你
鸟哥:
鸟哥一直进入答疑,然而这是恶作剧,并没有人问。

问题1:两次握手可以吗?

1)第一次握手
在这里插入图片描述

  • 第一次握手的时候,客户端发送 SYN 包之后,切换到 SYN 状态,这个和三次握手中的第一次是一样的。

2)第二次握手
在这里插入图片描述

  • 假设只有两次握手,那么服务端在获得 SYN 包之后就会进入到 ESTABLISHED 状态(请注意,这里服务端比客户端提前进入了ESTABLISHED状态,ESTABLISHED状态下会请求跟数据传输阶段有关的内存消耗,然后等待数据通信
  • 然后,回复给客户端SYN+ACK包,表示我收到了你的连接请求。

这里就是我们讨论的点:

  • 正常网络和用户请求(也就是每个请求都不需要重发,每个请求都是正常请求)的前提下,两次握手是足够,省了一次。
    在这里插入图片描述

  • 假设此时有网络延迟问题,客户端连续发送两个 SYN 包,是不是意味着 服务端会建立两个连接?来者不拒。(当然有人就说了,我是不是可以判断两次的SYN包呢,丢弃第二次。但是 我一个 ESTABLISHED 状态的 服务连接为什么还要消耗资源去处理 SYN 上的包呢?这个是我们需要考虑的地方)。

  • 假设网络是好的,根据来者不拒的原则,此时有个黑客想攻击我们的网络,不断发送 SYN 包,是不是意味着 我们服务端需要不断建立非常庞大的无效连接(每个连接都需要消耗内存资源)

  • 对标场景:

恶作剧A:你好,我是你的粉丝A,很高兴认识你,鸟哥立马进入答疑
恶作剧B:你好,我是你的粉丝B,很高兴认识你,鸟哥立马进入答疑

鸟哥一直进入答疑,然而这是恶作剧,并没有人问,浪费鸟哥时间。

两次握手的情况下,服务端比客户端更快进入了ESTABLISHED 状态,从资源消耗的角度来看,非常不合理(其实就跟手机用户访问网站一样,网站资源是非常珍贵的,反而是手机资源属于用户级别,浪费的只是自己的手机资源)。

结论

  • 两次握手导致服务端优先进入了 ESTABLISHED 状态,提前消耗了连接资源
  • 在普通情况(不存在网络攻击)下,客户端优先进入到 ESTABLISHED 状态,也是属于主动请求的一种表现,服务端收到ACK包之后才考虑消耗自己的资源,达到C-S的状态同步。
问题2:三次握手就可以了吗?是否考虑4次?

在不考虑网络攻击的情况下,三次握手已经满足了我们的要求,但是仍然解决不了网络攻击的问题。那么4次握手能解决网络攻击吗?
4次握手,其实就是形成了一个环形结构。从哪里来,回到哪里去。
在这里插入图片描述
这里你会发现,就算多一次,仍然解决不了,因为客户端可以伪装发送ACK,服务端一样会进入到 ESTABLISHED 状态。而且4次握手,白白浪费了一次传输时间 MSL。

3.2.2 断开释放连接阶段(四次挥手拜拜)

四次挥手即TCP连接的释放(解除):
在这里插入图片描述
在这里插入图片描述

1)第一次握手,客户端提出释放连接,发送 FIN(Seq = U),然后进入FIN-WAIT-1,也就是半关闭状态。停止客户端向服务端发送数据,但是客户端仍然能接收服务端传输过来的数据。(客户端从 ESTABLISHED 状态 变更为 FIN-WAIT-1 状态

2)第二次握手服务端收到客户端的FIN 包后,知道了客户端想要释放连接,随后服务端从 ESTABLISHED 状态 切换到 CLOSE- WAIT 状态,并且返回一个 ACK 包(Seq=V,Ack=U+1)给 客户端。记住,这个时候服务端可能还没有完全接收完客户端的数据(网络延迟),还在继续接收数据。客户端收到 ACK包之后,会进入到 FIN-WAIT-2状态.

3)第三次握手,当服务端确收完了所有数据,就会给客户端发送 FINSeq=w,Ack=U+1)包,表示我真的接收完数据了,此时会从 CLOSE-WAIT状态切换到 LAST-ACK状态

4)第四次握手,当客户端收到 FIN 包之后,会给服务端也发送一个 ACK 包(Seq = U+1,ack=w+1),同时给双方一个认真考虑是否真的释放连接关系的时间(考虑时间为2MSL,也就是一个网络来回的时间,也就是发送一个ACK包和FIN包的时间,刚好够服务端再次发送一个FIN包)。在考虑时间内,如果没有再次收到 FIN包,客户端就认为 服务端收到了 ACK 包,我们的关系到此结束。

在这里插入图片描述
业务场景:

…(省略好多字的交流)
粉丝A:我的整个问题问完了,谢谢鸟哥
鸟哥:没事,谢谢灵通
鸟哥:还有其他问题吗?
粉丝A:没有了,谢谢。

4.总结

源于与同事的互水讨论,更加对 TCP协议中的三次握手和四次挥手有更深刻的理解,在此谢谢大佬。

发布了138 篇原创文章 · 获赞 851 · 访问量 34万+

猜你喜欢

转载自blog.csdn.net/dpjcn1990/article/details/104989650