大家是否经常听别人提起TCP协议的三次握手和四次挥手呢?🤔是否看过很多相关的文章都没看懂或是没记住呢🤷?看过我上篇的小伙伴都应该知道TCP协议
是属于传输层中的协议,没有看过的请移步这里👉
“老默我想吃鱼了”与五层网络模型。
TCP协议
中的三次握手和四次挥手是计算机网络中最重要的知识点,也是我们面试过程中经常问到的点。TCP协议(Transmission Control Protocol,传输控制协议)
是处理可靠传输的,保证数据的正确性,只要使用这个协议,那双方的数据永远不可能错乱,多个字或者少个字的情况。
TCP收发数据流程
不知道大家是否还记得强哥第一次见大嫂是什么场景?花衬衫?深绿色西装?别猜了,看张图片帮你回忆😂
没错,第一次见大嫂提了一斤橘子,当大嫂看到强哥穿着很是诧异,完全不想搭理,但有句话说的好,不看僧面看佛面,看在橘子面勉强跟你唠唠,画了一张简图:
TCP收发数据流程也是如此,主要分为三个部分,首先是建立连接
,我们一般称为三次握手
,打完招呼之后就是正事了,互相交流寒暄,我们把这种互相交流称为收发数据
,我们需要注意的是这里的收发数据并不像HTTP请求那样,由客户端发出请求,服务端再响应,这里既可以由客户端发送到服务端,服务端也可以发送到客户端,如果把强哥比作客户端,大嫂比作服务端,就是强哥可以找大嫂说话,大嫂也能找强哥说话。当交流完毕后就say goodbye,一般称为四次挥手
,至于为什么要握三次手、挥四次手后面会说,莫急!🤤
TCP如何收发数据
自从强哥见了舒婷,便茶不思、饭不想、夜不能寐😶🌫️,懂的都懂,强哥是被舒婷谈吐气质深深折服了🤣,有一天,强哥准备发微信试探性问问舒婷内心真实的想法,以下就是强哥编辑的内容:
当强哥编辑了这么一大坨内容之后,是如何跑到舒婷的手机中的呢?TCP是通过分段
的方式进行传输的,之所以分段发送
是因为有时我们发送的东西特别多,容易造成阻塞,分段还有一个好处就是如果遇到丢包,后续只需要重新发送丢包的段即可,画个简图:
如果发送数据量很小的时候,就不需要分段了,一次性就过去。当数据量很大的时候,就要用到分段了,它会将整个数据分成段,按照字节进行编号,然后取出第一段,加上TCP头(蓝色方块)开始发送,紧接着取出第二段,再加上TCP头开始发送,依次类推,直到数据全部发完。
在TCP协议中,无论是发送方还是接收方,都可以主动给对方发送消息,数据传输的过程中,难免会出现数据报丢失、顺序错乱的情况,那么它是如何解决可靠传输问题呢?TCP协议规定:接收方收到数据报后,都要对数据报进行确认,用强哥和舒婷的例子来说,就是当强哥发了一大坨诗意的文字后,舒婷看到后回复一句:“好,我收到了,还有我不喜欢虚的,喜欢实在点的”,有句流行语叫“句句有回音,件件有着落”,就是这么个意思。但如果没有回应的话,那就表明数据出了问题,后续就需要重新发送了。
画个简图:
对照这个图,我们再走一遍可靠传输流程,当强哥将编写好的信息发送给舒婷时,如果数据量过大,就需要进行分段发送,取出第一段并携带TCP头形成数据报进行传输,这个TCP头部包含了很多的信息,其中就有seq
、ACK
、ack
seq
:全称sequence,表示这次数据报序号,就是整个数据被分成段之后发送每一段的序号,有了它我们就知道这次是发送哪一段的数据报ACK
:表示这次数据数据报是一个确认数据报,只能取0或1,相当于是个布尔值,为0时表示发送方发出的数据,为1时表示确认数据ack
:表示期望下次收到的数据报序号
当强哥开始发送消息时,TCP头携带seq=x
和ACK=0
,seq表示的是数据报序号,由于我们并不知道当前是发送第几个数据报片段,所以用x表示,ACK=0表示当前数据报还没有被接收方确认,当舒婷收到消息后,回应一句,你写的诗我看了,此时ACK就变为1,表示自己已经收到消息了,接收方已经确认,ack=x+1意思是数据报序号为x的我已经收到了,下次麻烦给我发送序号为x+1的数据报。但是如果发送方长时间没有收到数据报的确认(ACK=1),那就说明这段数据报出问题了,后续会重新发送。
建立连接(三次握手)
三次握手,想必大家都听过吧!为什么要三次呢?两次行不行?我觉得一次就行了,难不成想耍流氓?还有我怎么不知道TCP还有手呢?接下来依然用强哥和书婷的例子,让大家明白三次握手
遇到书婷之前,强哥从未谈过恋爱,也并不知道如何追女孩子,这不深夜联系了法医,经过我的细心指导,最终向强哥推荐了这本《魔鬼搭讪学》
如果有掘友想咨询感情问题,那就关注我吧!👉法医,教你们如何更快的分手,哈哈😂。
当强哥得知舒婷喜欢实在点的,不喜欢虚的,强哥准备用书信的方式表达自己的倾慕之情,以下是信的内容
然后强哥叫了一位美团小哥去送信,这一行为相当于TCP发起建立链接的请求,美团小哥走着走着迷路了,也不知道走哪里去了,那强哥的信肯定是送不到的,书婷自然也不可能有所回应,这一情况说明TCP的数据报丢失了,强哥长时间没有收到书婷的回应,说明ACK=0,此时强哥会重新写一封,继续叫一位靠谱的美团小哥送信,直到书婷有所回应,看来强哥也是一位专情的人🥰,希望大家都做一个对待感情专一的人💐
经过一番折腾,这封信终于到了书婷的手中,这一过程我们称为第一次握手,第一次握手后书婷知道强哥具有发消息的能力,但是书婷并不知道强哥是否可以收消息,这还得看送信人靠不靠谱,书婷联系了好评100%的饿了么小哥送信,书婷编辑了以下内容:
书婷让饿了么小哥送信的过程,我们称为第二次握手,不负所望,饿了么小哥成功将书信送到强哥手中,当强哥满心激动、小心翼翼地打开信封,看到书婷写的信,整个心都要碎了,泪流满面😭,深夜,正当我写文章之际,强哥不停敲打房门,当我打开门之后,看到泪流满面的强哥,急忙询问,强哥擦了擦鼻涕跟我说:“第一次表白就被拒绝了”,当我接过强哥手中的信,安慰说到:“女人心海底针,你没有被拒绝,看,人家称你为小强,说明你是打不死的小强”,强哥痛定思痛之后决定继续追求书婷。🤔
强哥收到书婷的信之后,我们称为第二次握手,此时知道书婷能收到强哥寄的信了,同时也具有寄信的能力,但是舒婷还是不知道强哥是否收到自己的信了,这时强哥回了一封信,并写道:“此生非你不娶!”,美团小哥安全将信送到书婷手中,书婷看了信之后心想:“这家伙还蛮有毅力的🤣”,当书婷成功收到信之后,我们称这次为第三次握手,此时书婷知道了强哥也可以收到自己的信了,这时强哥和舒婷都知道对方既有寄信的能力,又有收信的能力,表示通过三次握手的方式两人沟通渠道已经建立成功。接下来就是随心所欲的发送消息了。
画个简图:
我们过一遍这个图,当发送的数据过大时,会被分成一段一段的数据报,每一段数据报头部都会有TCP头部,这里面包含了很多信息,其中就有上图中的SYN(Synchronize Sequence Numbers,同步序列编号,是连接建立的握手信号)
、seq(sequence,数据报序号)
、ACK(Acknowledge character,确认字符,只有0和1)
每个链接都是从CLOSED
状态开始的,当它执行一个主动打开连接操作或者被动打开连接操作,它就离开了CLOSED
状态,当强哥开始寄第一封信的时候,链接从CLOSED
状态进入SYN-SENT状态
,TCP头部携带SYN=1
表示我要跟书婷建立同步链接、seq=x
表示这次发送的是序号为x的数据报、ACK=0
表示还未被确认的数据报,将这三个同时发给书婷,书婷成功收到信后,CLOSED
状态关闭并进入SYN-RCVD状态
,表示第一次握手成功,此时书婷知道强哥具有寄信的功能,但不知道的是强哥是否有收信的功能,这时书婷开始回信,第二次握手发生了,书婷的信携带TCP头部的信息SYN=1
表示我要跟强哥建立同步链接,seq=y
表示这次发送的是序号为y的数据报、ACK=1
表示强哥的信被确认的数据报、ack=x+1
表示序号为x的数据报已经收到,麻烦下次给我发x+1序号的数据报,当强哥成功收到书婷的回信后,第二次握手成功,强哥看了信悲痛欲绝、撕心裂肺、痛定思痛之后决定此生非书婷不娶,强哥此时已经知道书婷可以收到自己的信,但是书婷并不知道强哥已经收到自己的信,所以强哥需要再次写封信告诉书婷:“此生非你不娶”,这时第三次握手发生了,当书婷收到强哥的信后,书婷明白强哥是个专一的人,同时书婷也知道强哥可以收到自己的信,此时书婷和强哥双方都具有寄信和收信的能力,这一刻两人的连接就建立成功了,连接状态就变成ESTAB-LISHED
,表示正常的传输状态,可以互相交流了。😘
连接销毁(四次挥手)
三次握手我们已经知道,那四次挥手又是什么呢?为什么握手需要三次?挥手却需要四次?难道是对我依依不舍?
经过几天的书信往来,书婷渐渐对强哥也有了好感,加上第一次见面时的情景历历在目,强哥也是喜欢陪孩子玩耍的,其实男人除了疼爱自己的老婆时有魅力,还有就是带孩子,与孩子一起玩耍的时候,此时的他们少了父爱的光环,而蜕变成了一个活脱脱的孩子,像个孩子一样天真可爱。平时看上去不苟言笑的大男人,他们在当了父亲,陪伴孩子的时候,摘掉了社会发给他们的面具和伪装,心就像白云一样柔软和干净。我想这也是陈书婷喜欢强哥的一方面吧😎
这天安欣警官喊强哥一起吃猪脚面🍜,随后强哥修书一封告诉书婷:“安警官约我吃面,不能给你写信了”,强哥是个负责任的男人,虽然他很想和安警官一起吃面,但是他必须征求书婷的同意,所以强哥会等到书婷的来信之后再做决定。
当强哥写信告诉书婷:“安警官约我吃面,不能给你写信了”,这就是第一次挥手
,无论是强哥,还是书婷,都可以发起第一次挥手,我们暂且称为发送方
,每一次请求都需要被确认才可以,所以当发送方发起第一次挥手时,发完并不会立刻就挂,而是要等接收方
的回应。
不一会功夫强哥收到了书婷的回信:“小强儿, 我知道了,但是我还有最后几句话想跟你说,所以你先别去,等我说完”,然后书婷单方面的写了一大堆寄给小强儿,当把所有的话说完后,书婷写了最后一封信:“我想说的已经说完了,你去吧,等你忙完我们再联系”
书婷收到了强哥的来信,随后回复:“小强儿, 我知道了,但是我还有最后几句话想跟你说,所以你先别去,等我说完”,这就是第二次挥手
,这里发生了两件事情,第一件就是确认收到了强哥来信,知道强哥准备出门和安警官吃面,不能继续写信了,第二个就是书婷还要说几句话,然后书婷继续巴拉巴拉说,等书婷说完之后写了最后一封信:“我想说的已经说完了,你去吧,等你忙完我们再联系”,这是第三次挥手
强哥收到了书婷的来信:“我想说的已经说完了,你去吧,等你忙完我们再联系”,强哥也知道书婷的话也说完了,但是舒婷也并不知道强哥是否收到,所以强哥依然还需要进行回复:“好,我知道了,我吃完面回来找你”
强哥最后回复“好,我知道了,我吃完面回来找你”就是第四次挥手
,完成之后,连接销毁
画一张简图:
接下来我们详细的过一遍这个流程:
强哥和舒婷两人相聊甚欢,有一天,安警官约强哥一起吃猪脚面🍜,所以强哥写一封信:“安警官约我吃面,不能给你写信了”,这就是第一次挥手
,TCP头部有一个特殊的信息FIN(finish,表示想结束了)
,当FIN=1
时,说明这次的数据报准备销毁连接了,发送成功后,强哥的状态从ESTAB-LISHED
变为FIN-WAIT-1
,表示强哥已经说完话结束连接了,看线条1️⃣。
当书婷收到强哥的信之后,知道强哥约了安警官一起吃饭,不能继续写信聊天了,此时书婷的状态从ESTAB-LISHED
变为CLOSE-WAIT
,表示强哥已经发起了关闭连接。随后书婷写了一封信:“小强儿,你的信我收到了,我知道你要出去吃饭了,但我还有最后几句话要说”,这时候ACK=1
表示收到强哥的信了,用于确认数据报,这是第二次挥手
,用线条2️⃣表示,当强哥成功收到书婷的信后,强哥的状态从FIN-WAIT-1
变为FIN-WAIT-2
,表示书婷同意强哥去吃面,也就是同意强哥释放连接。由于接收方
(书婷)还没有发起断开连接请求,此时书婷依然可以进行数据传输,图中绿色箭头表示书婷说最后的几句话。
书婷说完之后,写了最后一封信:“我想说的已经说完了,你去吧,等你忙完我们再联系”,这是第三次挥手
,TCP头部包含了FIN=1
,说明书婷说完了,准备结束了,书婷的状态从CLOSE-WAIT
变为LAST-ACK
,表示所有数据报都结束了,用线条3️⃣表示
当强哥收到了书婷来信后,强哥也知道了书婷的话也说完了,也准备结束了,强哥也回复最后一封信:“好,那我出门了,等我回来再说”,TCP头部的ACK=1
表示确认收到书婷的数据报,这是第四次挥手,用线条4️⃣表示
图中有个特别重要的点,就是状态TIME-WAIT
表示等待所有数据报结束,左边还有一个2MSL
,MSL
是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,2MSL相当于是数据一个来回的时间,这里为什么要等待这个时间呢?主要是因为发送数据报不可能每次都成功,也有失败的时候,失败就需要重新发送,直到数据报被确认,这里假设第四次挥手线条4️⃣失败,没有发送成功,也没有等待2MSL
时间直接关闭进入CLOSED
状态,这时候书婷会认为强哥没有收到自己的信,路途中丢失了,那么会再次发送,但是强哥已经处于CLOSED
关闭状态了,这样会造成书婷不停的发送,但强哥始终确认不了,所以书婷的连接没有办法释放,迟早奔溃了。
补充的点
这里给大家补充一个点,看到这里我想大家也都知道数据包如果很大,会被分成一个个数据报片段进行传输,那么数据报片段在哪里组装成一个完整的数据呢?有一个地方叫做数据缓冲区
我们继续用强哥和舒婷的例子,书婷无论是从谈吐、气质都是优秀的女孩,那肯定追求者不会少,强哥只是其中之一
画个简图:
这里书婷相当于服务器,而四位追求者相当于客户端,客户端和服务器每一次传输数据都会经过三次握手和四次挥手,数据报片段都会在数据缓冲区进行组装,每次通过四次挥手销毁连接,也就是清除缓冲区释放空间,当我们每次打开浏览器页面的时候,打开几个页面感觉不到卡,那你的打开100个页面试试,当然这跟电脑配置也有关系。
我想大家现在也应该明白,为什么要使用三次握手和四次挥手?理想状态一直连着不好吗?想请求数据随时请求,干嘛还要断开,主要还是因为减少服务器的压力,尽管三次握手和四次挥手会损耗一些时间,但是用这些时间换去服务器的空间是非常划算的。
最后
欲知后续如何?请听下回解说,关注我不迷路👉法医,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下啊~🌸
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。