应对前端校招之-TCP连接中的三次握手与四次挥手

759 阅读7分钟

前言

相信如果你经历过前端校招面试的话,那么客户端和服务器端在建立连接时的三次握手与断开连接后时的四次挥手一定是一个无法绕过去的坎,那么今天就让我来浅谈一下究竟是什么三次握手和四次挥手~

概念和定义

三次握手

三次握手(three times handshake;three-way handshake)所谓的“三次握手”即对每次发送的数据量是怎样跟踪进行协商使数据段的发送和接收同步,根据所接收到的数据量而确定的数据确认数及数据发送、接收完毕后何时撤消联系,并建立虚连接。

还是老话,定义就不是正常人看的,那么还是让我来给大家配图来讲解一下到底三次握手是怎么样的一个流程

首先我想先跟大家明确一点,就是客户端和服务器端建立连接为什么非得三次握手不可,两次不行吗?四次不行吗?

这里我想先跟大家做个比喻:

假设现在你的异地恋女友买了一只新手机,兴致冲冲地想要发消息向你共享这个好消息,那么你和你女朋友如何能确认新手机的微信功能好使,并开开心心的进行聊天呢?

此时,你女朋友向你发了一条消息说亲爱的,我新买了一只iphone x,你能收到我的消息吗?然后她就进行了焦虑的等待中,因为她不知道她这条短信是否发送成功,也并不知道你是否成功接收了这条短信.(第一次握手)

过了一会儿,你收到了来自异地女友的那条消息,此时你已经知道你女朋友新买的手机发送功能是没问题的,然后你还知道你的老年诺基亚手机竟然接收功能仍然是正常的,你为了顺道再测试下自己的诺基亚发送功能是否完好,你就编辑了一条信息回了过去说亲爱的,你的短信我收到啦,真羡慕你的iphone x发送功能这么强大,也不知道我诺基亚的发送功能还好不好使呢~(第二次握手)

然后,你就进入了心里没底的等待状态,不知道自己的短信能否被女朋友看到.不久,在异地的女朋友收到了你的短信,此时她已经知道了自己的iphone x的收发功能都是完好的,然而为了通知你你的诺基亚发送功能也没问题,她不得不不情愿的再编辑了一条消息发送说:知道啦,你的诺基亚不还能用吗,老老实实的再用个几年呗. 最后,你成功收到了你女朋友的信息,然后承认了自己诺基亚还能再战十年的事实,老老实实地用诺基亚和女朋友开始了深度交流(第三次握手,连接建立)

三次握手的意义

所以总的来说,三次握手的意义就在于让客户端和服务器端双方都确认对方的收发能力正常,然后才能开始进行数据的传输

图解三次握手

根据上图可知,第一次是客户端主动向服务器端发送请求,然后进行了第一次握手.这里我们可以看到客户端向服务器端发送了两个包,一个叫SYN,一个叫seq.

那么SYN指的是什么? seq又指的是什么呢? 其实简单来说,SYN(同步序列编号Synchronize Sequence Numbers)就是一个建立连接的标志位,当置为1的时候表示请求建立连接.还有一个包叫做seq(sequence number)表示的是发送数据包的第一个字节的序列标识

第一次握手的时候,客户端向服务器端发送一个SYN=1,表示建立连接,seq=x,表示数据起始位置是x,然后客户端进入SYN_SENT状态

第二次握手的时候,服务器端向客户端返回了一个ACK (Acknowledge character)=1的包,表示确认收到.另外还有一个ACK = x + 1,表示希望客户端下次发送的数据从x+1处开始发送.然后服务器端再向客户端发送一个SYN=1(同上表示建立连接),seq=y(同上表示发送的数据起始位置是y),然后服务器端进入SYN_RECEVIED状态

第三次握手的时候,客户端向服务器端发送一个ACK = 1(同上,表示收到),再发送一个ACK = y + 1(同上,表示希望服务器端下次发送的数据从y+1处开始发送).最后才发送一个seq,此处因为服务器端要求客户端从x+1处开始传输数据, 所以seq = x + 1,发送完成后客户端进入ESTABLISHED状态,而服务器端收到后最后也进入ESTABLISHED状态.

四次挥手

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

先来看下大致的流程图

四次挥手的意义

四次挥手的意义和三次握手差不多,都是需要确认客户端和服务器端双方都断开连接后,才会关闭连接

图解四次挥手

首先可以看到,四次挥手与三次握手的第一个不同点在于,四次挥手的主动方和被动方是不固定的(也就是可以由服务器发送断开请求,也可以用客户端发送断开请求),这就和三次握手形成了差别

可以看到第一挥手,主动方发送了一个seq=x的包,这个与上面的三次握手一样,表示数据的起始位置是x,然后又发送了一个FIN=1的包(表示断开连接,与SYN=1形成对比),此时主动方会进入FIN_WAIT_1的状态

第二次挥手,服务器会向客户端发送一个ACK=1(表示收到)的包,然后再发送一个ACK=x+1的包表示希望客户端下次发送的数据从x+1处开始传递,此时服务器端进入CLOSE_WAIT状态,客户端接收到服务器发送的包后,进入FIN_WAIT_2状态

第三次挥手,等到服务器端准备完成后,向客户端发送一个FIN=1(表示断开连接)的包,然后再发送一个seq=y,表示发送的数据从y开始,此时服务器端进入LAST_ACK的阶段

第四次挥手,客户端接收到服务器端的消息后,向服务器端发送一个ACK=1(表示已收到),再发送一个ACK=y+1,表示希望服务器下一次发送的包的位置,进入TIME_WAIT状态.

最后,客户端会等待2MSL(2个最长报文段寿命),如果服务器端没有重传数据包的话,那么说明服务器端已经收到完整的数据包,服务器端最终进入CLOSE状态,然后客户端也进入CLOSE状态,到此四次挥手结束,TCP断开连接

总结

常见的可能考点

  • 在三次握手和四次挥手之间发送的各种包(都需要明白其意思)
  • 为什么建立连接需要三次握手,断开连接需要四次挥手?
    /*
    *   为什么要三次握手相比前面已经讲清楚了,那么四次挥手的意义在哪里呢?
    *   首先我们可以看到,服务器在第二次挥手的时候,没有立刻向客户端发送一个FIN包
    *   原因在于,服务器在刚收到客户端的断开连接请求后,还没有做好断开连接的准备
    *   所以服务器端会等待一段时间,直到自己做好准备,再发送FIN=1这个包,也就是第三次挥手
    *   这样一来,也就变成了四次挥手
    */

最后

祝大家秋招顺利,都能拿到自己心仪的offer~