本文以博主在某次前端面试中被问到“什么是TCP协议中的三次握手和四次挥手?”为契机,经过整理教材、百度百科以及他人博客,再结合博主自身的理解,尽可能的以通俗易懂的语言来解释TCP协议中的三次握手和四次挥手的具体过程。
客户端与服务端在建立TCP连接时需要经过三次握手才能建立,而断开连接则需要四次挥手。整个过程全览如下图所示:
我知道,直接看此图,相信大多数伙伴是懵逼的,下面我们就分别从建立连接和断开连接进行详细介绍。
客户端与服务端在建立TCP连接时需要经过三次握手才能建立,其具体过程图解如下图:
上图中间的三个箭头即为三次握手。
第一次握手:建立连接时,客户端发送SYN包(SYN=j)到服务器,此时客户端进入SYN_SENT状态,并挂起等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:当服务器收到客户端发来的SYN包后,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态。
至此完成三次握手。
怎么样,懵逼吧,我都说了,这种说明,说了也是白说!
其实建立连接三次握手的过程跟我们平时打电话的过程是一样样的,我们来看这样一个场景:
某天,隔壁老王给隔壁老张打电话,有如下对话:
老王:天王盖地虎!
老张:天王盖地虎,小鸡炖蘑菇!
老王:小鸡炖蘑菇!
电话接通,老王和老张Blalalala....
下来我们结合上面三次握手的图解仔细分析下这个场景,
首先,老王给老张打电话,老王就是客户端,老张就是服务端。只有老王给老张打了电话,老张才会去接电话,也就是说老张不会主动去找老王,只有老王找老张,老张才会应答老王。
对应到上图中就是客户端主动打开,服务端在监听等待,只有当客户端主动发起建立连接请求的时候,服务端才会配合客户端进行连接。
当老张听到老王说的“小鸡炖蘑菇”后,老张心想“嗯,老王也能听到我说话”。如此,通过以上过程,老王和老张就知道对方能听到自己说话,接下来就可以Blalalala....
听完这么一分析,是不是豁然开朗!!!
建立连接一定要握手三次吗?两次握手为什么不行?四次握手为什么不行?
还是以老王给老张打电话场景为例,
先看两次握手:
老王:老张,你能听到我说话吗?(第一次握手)
老张:我能听到,老王,你能听到我说话吗?(第二次握手)
此时,两次握手结束,按理连接已经建立成功,可是老张还不知道老王能不能听到自己说话,所以接下来
老王:我们今天去老刘家打麻将吧
老张:我能听到,老王,你能听到我说话吗?
老王卒。
再看四次握手:
老王:老张,你能听到我说话吗?(第一次握手)
老张:我能听到,老王,你能听到我说话吗?(第二次握手)
老王:我能听到,老张,你能听到我说话吗?(第三次握手)
老张:我能听到。(第四次握手)
老王和老张Blalalal....。
显然,两次握手根本就无法建立连接,而四次握手虽然可以建立连接,但是耗费资源啊
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。断开流程如下图所示:
上图中间的四个箭头即为四次挥手。
TCP从连接到断开总共要经历十种状态,如下图:
连接之前,服务端处于LISTEN(1)状态,当客户端向服务端发送连接请求SYN后,客户端处于SYN_SENT(2)状态,当服务端收到请求并发送回应SYN+ACK后,服务端处于SYN_RECV(3)状态,当客户端收到服务端的回应后,客户端处于已连接ESTABLISHED(4)状态,并向服务端发送ACK,最后服务端也处于已连接ESTABLISHED(4)状态
断开之前,当客户端向服务端发送断开请求FIN之后,客户端处于FIN_WAIT1(1)状态,服务端收到FIN之后,服务端处于CLOSE_WAIT(2)状态,服务端向客户端发送ACK回应,此时客户端处于FIN_WAIT2(3)状态,服务端也即变为LAST_ACK(4)状态,服务端向客户端发送FIN请求,客户端状态变为TIME_WAIT(5),最后,客户端向服务端回应ACK,客户端和服务端状态都变为CLOSED(6)。
至此,TCP连接的三次握手和四次挥手全部总结完了,懂没懂就看个人理解了,反正我也是费了好大劲才理清其中的关系。
原文:https://www.cnblogs.com/wangjiachen666/p/9610338.html