有这么一道面试题:为什么TCP协议握手是3次,挥手是4次?

围绕着这个问题,接下来会详细的讲讲涉及到的知识

TCP协议

TCP(Transport Control Protocol)是一个传输层协议,提供 Host-To-Host 数据的可靠传输,支持全双工,是一个连接导向的协议。

主机到主机(host to host)

TCP协议提供的就是host to host传输,一台主机通过TCP传输数据到另一台主机。 主机并没有明确的概念,可以是任何可以接受和发送数据的设备,双方即是平等的。

TCP协议往上就是应用到应用(ATA——application to application),举一个很简单的例子:A用QQ给B发送消息,那么QQ客户端,QQ聊天服务就是应用的载体,QQ是有自己的聊天协议,其就是应用到应用的协议,如果QQ想要的聊天协议想要进行工作,那么就要一个主机到主机的协议帮助实现通信
而 TCP 上层有太多的应用,因此 TCP 上层的应用层协议使用 TCP 能力的时候,需要告知 TCP 是哪个应用——这就是端口号。端口号用于区分应用

TCP 要实现主机到主机通信,就需要知道主机们的网络地址(IP 地址),但是 TCP 不负责实际地址到地址(Address-To-Address)的传输,因此 TCP 协议把 IP 地址给底层的互联网层(网络层)处理。

互联网层,也叫网络层(Network Layer),提供地址到地址的通信,IP 协议就在这一层工作。

互联网层解决地址到地址的通信,但是不负责信号在具体两个设备间传递。因此,网络层会调用下方的链路层在两个相邻设备间传递信息。

当信号在两个设备间传递的时候,科学家又设计出了物理层封装最底层的物理设备、传输介质等,由最下方的物理层提供最底层的传输能力。

以上的 5 层架构,我们称为互联网协议群,也称作 TCP/IP 协议群。总结下,主机到主机(Host-To-Host)为应用提供应用间通信的能力。

连接 & 会话

  • 连接:连接是数据传输双方的契约,就是保证双方都在线,并且尽快地响应对方的请求。从设计上来考虑,连接是一种传输数据的行为:传输之前,建议一个连接,具体而言就是数据收发双方的内存里都建立了一个用户维护数据的传输状态的对象,记录了双方的ip地址和端口号,传输速度,发送状态是否完好,发送了多少数据,还剩多少数据等等,我们就此也可以总结出:连接是网络行为状态的记录
  • 会话:会话是应用的行为,说得简单易懂一点那就是我和对方使用QQ打开了一个聊天窗口,这个就是会话,开始打字发送那就是建立了和qq服务器的链接,不关闭对话窗口那就是会话还在。在一部分的系统设计中会话是会保持重启的,(重新创立连接),此外会话也会帮忙在多次连接中保持状态,最好距离的就是http session中多次http请求中保持了用户的token信息,那就是一种状态保持

    通上:连接是传输层的东西,会话是应用层的东西

单工 & 半双工 & 全双工

  • 单工:无论在任何时候,数据只能单向发送,这也就导致了单工至少需要一条线路
  • 半双工:在某个时候,数据可以朝着一个方向传输也可以朝着另一个方向反向传输,并且交替进行,这就叫半双工,同理,这也需要至少一条线路
  • 全双工:无论何时,数据都可以双向收发,需要大于一条线路
    TCP协议是一个全双工协议,任何时候都可以进行双向收发数据意味着客户端和服务器可以平等的收发数据,也正因如此,在TCP协议中客户端和服务端有一个平等的名词叫做主机(Host)

什么是可靠性?

TCP协议提供可靠性,指的是数据保证无损传输,如果发送方是有序的传输数据,但是数据在网络间无序的传输,那么就必须要有一份可靠的算法在接收方将数据恢复到原来的顺序。如果接收方有多个,这种情况我们称之为多播,可靠性要求每个接收方都要收到无损的相同的副本,另外,多播情况下还有强可靠性要求,即:一旦有一个接收方收到了消息,那么所有的接收方都必须要收到这个消息

TCP的挥手和握手

TCP是一个连接导向的协议,没有设置会话,因为会话通常是应用层的应用功能,其自身设计有建立连接(握手)和断开连接(挥手)的过程

TCP协议的基本操作

  1. 如果一个Host主动向另一个Host发送连接,称之为SYN(Synchronization),请求同步
  2. 如果一个Host主动断开连接,称之为FIN(Finish),请求完成
  3. 如果一个Host主动向另一个Host发送数据,我们称之为PSH(Push),数据推送

以上 3 种情况,接收方收到数据后,都需要给发送方一个 ACK(Acknowledgement)响应。请求/响应的模型是可靠性的要求,如果一个请求没有响应,发送方可能会认为自己需要重发这个请求。

建立连接的过程(三次握手)

要保证连接和可靠性约束,TCP协议每次发送数据都要收到ACK(响应),那么按照这个思路:

  1. 客户端发送请求给服务端(SYN)
  2. 服务端准备好连接
  3. 服务端给客户端发送一个ACK告知客户端准备好了

咋一看好像没问题了?但是服务端还不知道客户端OK不OK呢,于是我们继续:

  1. 服务端发送一个SYN给客户端
  2. 客户端准备就绪
  3. 发送ACK给服务端,说,准备好了

那么到此就是结束了整个流程,再来分析一下为什么是3次握手:

  • 步骤一:是一次握手
  • 步骤二:只是服务端的单方面准备,并没有数据传输,那么不算握手
  • 步骤三和步骤四,都是服务端发送给客户端的数据传输,同时发生,我们可以合并为SYN-ACK响应,作为一条数据响应给客户端,算一次握手
  • 步骤五:同理步骤二
  • 步骤六:是一次握手

断开连接的过程(四次挥手)

那么继续上面的思路,可以设想:

  1. 服务端发送要求断开连接的FIN
  2. 客户端收到,发送ACK响应
  3. 注意,这里不能像握手那样马上传FIN回去
    其实这个时候服务端不能马上传 FIN,因为断开连接要处理的问题比较多,比如说服务端可能还有发送出去的消息没有得到 ACK;也有可能服务端自己有资源要释放。因此断开连接不能像握手那样操作——将两条消息合并。所以,服务端经过一个等待,确定可以关闭连接了,再发一条 FIN 给客户端。
  4. 客户端收到服务端的 FIN,同时客户端也可能有自己的事情需要处理完,比如客户端有发送给服务端没有收到 ACK 的请求,客户端自己处理完成后,再给服务端发送一个 ACK。

总结

不要死记硬背这个握手和挥手,而应该去理解他:

  1. TCP提供连接,让双方的数据传输更稳定,更安全
  2. TCP没有直接提供会话,因为会话的需求多种多样,比如QQ保持对话双方的聊天记录,游戏保持了在线和各种记录,电商平台保持了购物车和订单的一致等等,所以会话通常在TCP的上一层封装,也就是说在应用层
  3. TCP 是一个面向连接的协议(Connection -oriented Protocol),说的就是 TCP 协议参与的双方(Host)在收发数据之前会先建立连接
  4. 最后,连接需要消耗更多的资源。比如说,在传输数据前,必须先协商建立连接。因此,不是每种场景都应该用连接导向的协议。像视频播放的场景,如果使用连接导向的协议,服务端每向客户端推送一帧视频,客户端都要给服务端一次响应,这是不合理的

那么说了这么多,让我们最后来回答一下面试题的问题吧:

答案:

TCP 是一个双工协议,为了让双方都保证,建立连接的时候,连接双方都需要向对方发送 SYC(同步请求)和 ACK(响应)。

握手阶段双方都没有烦琐的工作,因此一方向另一方发起同步(SYN)之后,另一方可以将自己的 ACK 和 SYN 打包作为一条消息回复,因此是 3 次握手——需要 3 次数据传输。

到了挥手阶段,双方都可能有未完成的工作。收到挥手请求的一方,必须马上响应(ACK),表示接收到了挥手请求。类比现实世界中,你收到一个 Offer,出于礼貌你先回复考虑一下,然后思考一段时间再回复 HR 最后的结果。最后等所有工作结束,再发送请求中断连接(FIN),因此是 4 次挥手。

最后修改:2023 年 02 月 10 日
收款不要了,给孩子补充点点赞数吧