请描述TCP三次握手和四次挥手,这是非常常考的一道面试题。
大家不要去追求过多的细节,你如果是搜一些文章或者答案的话,它会给你描述的很细。
然后我/你看到会很懵,因为这里面如果讲细了的话,需要很多这种网络请求的相关的底层知识,
比如说包的一些格式以及包里边的一些数据代表什么意义?
其实这个对我们来说没有任何的价值,因为这东西对我们的开发没有任何的指导价值,指导意义,
它是太底层的东西,不需要我们关注。
这个是操作系统和网络请求本身,它帮我们完成的一些东西,所以说这个不用去关注,你需要关注的是什么?
第一个为什么会有三次握手和四次挥手?
为什么是三次、四次不是两次?
握手是什么?挥手是什么?
你能大概讲出来这个东西的过程,以及它本质的一个原理/原因就可以了。
对于这种和我们开发不相关的问题,面试官/你不用追求的那么细致,你即便是讲的很细致,你得100分。
你讲的不是那么细致,那你得80分都能通过,但是请你注意一下,你要想得100分那个成本是太高太高太高了。
甚至几乎不可能得到【抓包,报文结构,这些信息文字描述很不方便,属于过程信息,要动手实践的】,
因为你不可能说为了这道面试题,然后你再把网络请求那本书全部复习一遍。
这个完全没有必要,但是你想得个80分,那是还是很容易的,本博文的讲解大概基本上就能得个80分。
这是最好的一种方式,我会用非常非常通俗易懂的语言把三次握手和四次挥手讲明白。
首先说握手挥手这两个词,握手是什么?
握手是表示友好。
进屋一见面,两个人一握手,证明什么?
连接上了,关系连接好了,握手是TCP连接的一个过程。它需要三次握手,握手是连接。
挥手呢?
挥手就是告别,我挥一挥衣袖,不带走一片云彩。
挥手是告别。握手是连接。
告别如果是用专业来说就是断开,也就说握手是TCP的连接,挥手是TCP的断开。它需要四次挥手的过程才能去断开,
那我们看一下为什么是三次以及为什么是四次?
首先,建立TCP连接。
我们要先建立连接,要确保双方都能收发消息的能力,
然后呢,我们才能进行传输内容。比如说我们发一个GET请求对吧,
这两个是不一样的标准,建立连接,包括我后面断开连接都是TCP协议的。
GET请求 传输内容是HTTP协议的。其实我们日常使用的东西呢,大部分都是 HTTP 协议的。
但是面试的时候呢,会更加苛刻一些,会让你讲到TCP协议的一些东西,
技术是技术,工作是工作,面试是面试。虽然说面试会涉及到更多的范围,但是既然涉及到更多的范围,它就不会要求那么精确的一些深度。有广度就不能有深度。
像我们后端开发,就不会要求对TCP协议了解的那么深入【那是网络工程师干的事情】。
只需要知道这个过程就可以了。
比如说你想要找人去你的朋友家去取一个东西,或者说你想要找人把你的东西送给一个朋友家。你该怎么办呢?
你直接就去吗?当然不是,
先打个电话或者发个微信问一问在不在家啊?在家的话就去,而且你要等着,我现在就要去派人去,
如果不在家,那你去了不是白去吗?
所以建立连接就是一个打电话或发微信的这么一个过程,来确保我们的双方都可以收发消息,这样才可以。
好,我们看一下三次握手建立连接。咱举个例子来说:
比如说就是想找个人,然后去 沉默王二 家。
第一条线就是跟我相关的一些线。
第二条就是跟沉默王二相关的一些线。
我现在想要去派一个人去沉默王二家取个东西,或者说我想要去派人把我的东西送给沉默王二。
应该是三个过程,
第一个过程就是建立连接。
第二个过程就是送或者说收。
第三个过程就是断开连接。
建立连接的过程,其实就是我们说的三次握手。
三次握手的过程,就是我们现在要看一看为什么是三次。
因为我代表的是什么?是客户端,沉默王二 代表的是服务端。
如果是按照我们人本身比较形象的理解,我打个电话就行了,对吧?打个电话,然后问一问,
但是计算机之间它没办法像我们人这么人性化的打电话,它需要类似于那种发短信【发数据包】的那种形式去收发消息来去确定,来去建立连接,来去确定 沉默王二 在不在家。
所以说我们就用发短信 举例子,
首先第一步。因为我需要主动上 沉默王二 家去拿东西,所以我需要发个短信告诉去问 沉默王二 。
问他在不在家,这是第一步,
沉默王二 如果不在家,没收到,那没招,那后面没法进行正常响应。
沉默王二 如果在家,就正常响应,
他收到短信了,他会怎么说呢?他会告诉我,说给我回个消息,说我在家了,
还没完,你只是问在不在家,然后他说我在家了,
那下一步该怎么做?他说他还不知道,
所以说你需要再发一个消息告诉 沉默王二 说 OK 你等着。
我过去拿东西。到这一步,这个连接才算是建立完。
这就是三次握手。
为什么是三次握手?
第一次是先发个消息问你在不在家,
然后 沉默王二 回复在家了。
然后你再发消息说好,那你等着我,我这就过去,
这个时候 沉默王二 收到消息之后,他才会等着你。
这是我们的例子。那我们可以比较专业的去说 client 发包 server 接收,
这个时候 server 就知道,哦,原来这个 client 要找我。
server 已经知道了,然后 server 发包,client 接收,client 就知道,哦,原来 server 已经收到消息了。
这个时候其实这两步双方就已经相互证明了 对方原来有发消息的能力,
但是这个时候要不要开始发呢?还没确定,所以说就需要第三次发包,client 发包,server 接收。
server 就是这个时候就知道了 client 原来要准备发送了,所以说我得准备好,我在等着,
我不能随便关了,它发来之后,接收完消息之后,我再去关闭。
所以说就需要这个三次握手才能把这个连接完全建立好。
前两步是确定双方都有收发消息的能力,然后都同时在线,
然后第三步就是 client 告诉 server。别走,我要准备发送了。
然后接下来立马开始进行收发消息的能力,
大家看这个箭头的意思就是先client往这个server发。
然后server去回传/响应 消息,
然后client再往server发,
专业的图是这样的:
其实这个东西和我们刚才画那个图是完全一样的。只不过它是用专业的术语去答,
但是大家千万不要纠结于这个专业的术语。
每个单词是什么意思?每个包里面什么内容是什么形式?
它为什么会有这种形式?这个都是计算机网络这个底层里面的一些规定,一些协议。
TCP的一些协议,这个我们不用关心,我们只需要知道这个三次握手,它为什么需要三次就可以,
以及知道三次握手它是个连接的过程。
三次才能稳定的连接。
好,连接完之后在下面才开始传输消息,这个就是 ESTABLISHED 之后,下面就是所有的传输消息的过程。
那接下来我们就可以在这个地方去画一下,比如说我和沉默王二已经建立连接了,那好,那我就派人去取了。
然后一趟两趟的把东西/data拿过来,就是这样的收发消息的过程。
是不是就结束了?没结束对吧?因为还没有断开,还没有关闭,如果沉默王二一直等着你,
或者说你一直等着沉默王二,这不对,大家都很忙,抓紧时间说话,完了之后,抓紧时间干别的事情去。
所以接下来就是四次挥手,断开连接,就是你们两个断开了之后,你该干嘛干嘛,他该该干嘛干嘛,
即便是断开之后,对方死机了。对方不在线了,对方停电了,这都没关系,
但是在断开之前,那你不能死机,不能停电,你不能掉线。
这个时候会影响整个完整的一个请求过程。我们先不说,我们先去还是继续说完这个例子。
接下来呢,我们就开始断开的过程,断开,
它需要是四次挥手,,断开,肯定是由我来发起,因为这个连接是我来发起的,断开是由我来发起。
因为什么时候断开是我说了算,我是主动方,所以说第一步消息就是我告诉沉默王二。【完事了】
我完事了,我的请求已经发完了。但是这个时候是不是所有的东西都拿过来了呢?还不一定,
我第一步只是告诉沉默王二,我的请求已经结束了,我没有再多的请求了。但是这个时候的数据传输有可能还在进行中,
所以说第二步是什么?【继续运】第二步是沉默王二告诉你,行,我知道了,我知道你没有请求了。
但是这个时候呢,可能沉默王二还在继续给你运东西,还没有运完,所以说沉默王二只是知道了你没有请求到这件事。
但是可能还会继续运,这个时候呢,沉默王二继续忙活,
我呢,就在这等待,当沉默王二忙活完之后,沉默王二会接着再给我发一个消息说。
行了,我该给你的东西全部给你了,这个时候你可以选择断开了,【给完了】
然后到这一步之后,然后我再告诉沉默王二。说行,我收到东西啦,然后你就断开啦。【收到了】
这一步之后,沉默王二就可以去断开了。
这是一个完整的断开流程。
就是我先告诉沉默王二,我这没要求了,你那边忙完就可以断了。
沉默王二回复好的,然后接着忙,忙一阵之后,
沉默王二再回复。就是忙完之后,沉默王二再回复说,我这边已经忙完了,你看要不要断开,
然后我就告诉沉默王二,行,断开吧,然后他又断开了。这就是整个的四挥手的过程。
主要的区别在于什么地方呢?
在于这个地方为什么是两步?【见断.四次 黑色方块】
如果我们专业讲的是这样,就是我们一次 HTTP 请求,它 有完整的 Request,还有完整的Response。
比如说我们请求一个网页回来的Response 就是一堆 HTML 的代码。
但实际上我们讲的是TCP底层的协议,HTTP 请求是HTTP的协议,这两个是不一样的,
实际上,我们在发送一个HTTP请求的时候,它背后有可能是有好多个琐碎的细节的TCP请求。
或者说数据的传输来完成的,
最后,它会把这些琐碎的东西全部拼接在一处。整合成我们需要的整个的一个完整的结果,所以说我们看似是一步请求,实际上在计算机内部有可能是发了很多个包才能拼接出这个请求。只不过这个东西是计算机网络模块帮我们合并起来了,我们自己内部无法感知而已,
所以说在真正的请求里边。这个地方必须要发送两步,为什么呢?
因为中间有可能还会有很多细节的一些请求还没有完成,这个请求我们看似是一个,但实际上它可能划分了好多块。
特别是一些比较大的文件,这个情况更加明显一些,
所以说这块得有两部分去完成。
第一部分是告诉你知道了,第二部分是真正的是发送完成之后,然后告诉我可以关闭。
第一步,完成之后不能关闭。整个全完了之后才能关闭,
所以说这块要注意一下,为什么这是四次挥手就断开,为什么需要四次。
我们接着看一下比较专业的过程。
1)client发包,server接包。然后server知道了,哦,client已经请求结束了,
2)稍后server发包,client接收,就是client这个时候server已经收到了,那我就等着吧,server它还没有发完。
3)然后server发包,client接收,client就说,知道了,server此时已经可以关闭连接,它已经发完了,它可以关闭了。
4)那server它可以关闭,因为server它没有这个主动权,那client我就告诉它server,client发包,server接收。然后server就知道,哦,原来client告诉我已经可以关闭了,然后就关闭连接。
这就是整个的四次挥手的过程。
回顾四次挥手的过程。
第一步,client发给server,
第二步,server返回client,
第三步,server忙完之后看这个finish返回client,
第四步,client再告诉server说可以关闭。然后server这个地方close就关闭,
是这么个过程。
然后总体来看就是这么一个过程:
就是先通过三次握手来进行连接。三次握手,是三次。然后中间传输,后面呢,经过四次挥手。然后去断开,是四次挥手,
如果面试遇到这个问题,你可以画这么一个图,然后把这几个箭头画上,然后讲解一下它是什么样的,大概一个过程就可以了。
划重点,握手是连接三次,握手是连接,挥手是告别,告别就是断开。
四次挥手就是断开,然后千万不要追求深入的细节【不要说SYN ACK FIN 之类的名词】,否则会带给你很大很大的成本。