TCP握手详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Double_Name/article/details/51193679

对于TCP链接我们首先要有一个基本认识是:TCP链接的开启和关闭都是做好了最坏的打算,以保证在网络情况最不稳定的情况下仍然可以成功的发送和结束TCP链接,这就好比我们做任何事都要考虑到最坏的情况一样,这充分说明了设计者的睿智,不是吗?

在这个基本认知的基础上我们先来看看开启链接的3次握手是什么情况:

现在假设有这么一个情景:

      A(北京)要和B(上海)进行信件来往,

A首先给B发了一封信,-----“信件送往过程(一天?两天?呵呵!)”------B成功接收信件(第一次握手)

解析:A怎么知道信件有没有到达B呢,A等了一段时间之后没消息,没关系,重新发送,我就不信你接不到!!!!

B接到之后就要给A回信了,----“信件送往过程(这次直接飞鸽,一天!)”-----A成功接收到了B的来信(第二次握手) 

解析:B又是如何知道A成功接到了B的回信呢,显然B不知道。于是就有了第三次握手

A接到B的回信之后再给B确认接收的信息-----“信件送往过程(这次坐火箭!!)”----B接到A的确认信息(第三次握手)

在经过以上的步骤之后A和B就能保证绝对成功通信一次了,有可能A对B说了一句我爱你呢,B欣然接受了呢,这不错促成一段姻缘。。。。以上情况我们保证了再最坏的情况下A也和B进行了互相的表白了,接下来让我们看看TCP的三次握手吧:

http://img.my.csdn.net/uploads/201108/7/0_1312718352k8l6.gif

首先第一步:TCP链接必须有客户端开启呦。(就好比购物过程一定要由顾客开始一样,你说我不买东西你非卖给我是不是找抽啊),客户端想要开启连接,于是就给服务端发送一个SYN包(SYN是一个用于在建立连接时候用于数据传输的数据包)。

第二步:服务端接收到这个SYN包之后就知道客户端想要开启连接了,于是乎就屁颠屁颠的在回应一个SYN+ACK包给客户端。

第三步:当客户端接收到这个SYN+ACK包的时候就知道服务端已经做好开启连接的准备了,于是客户端就想着既然你服务端都准备好,我也准备好了,那咱就开始吧。然后就再给服务端一个ACK包告诉服务端“我客户端已经知道你做好准备了,咱们开始干吧!”.就这样,一段TCP连接就开启了。


大家知道天下没有不散的宴席,既然有开始,那么肯定就有结束喽,下面我们看看结束过程吧:

http://img.my.csdn.net/uploads/201108/7/0_1312718564tZXD.gif

首先我们明确一个概念:再让我们调用一个顾客买东西这个例子,顾客买东西不成功有啥原因,一方面可以使顾客不想买(价钱,款式问题),第二方面是因为卖家觉得顾客不够帅,价钱出的低赔本了。这都会导致这次交易不成功,其实关闭连接也差不多,服务端会因为某种原因提出关闭(服务器故障等原因),客户端也可能提出关闭连接(关闭当前页面,掉线。。。),所以我们要明确一个概念就是开始是单方的事,但是结束可是双方都有权利的。

关闭连接的过程主要是4步:

现在我们仍然假设是客户端提出关闭连接(当然服务端提出也有可能,情况类似,不在讨论)

第一步:客户端提出要关闭连接了,于是就给服务端发送一个FIN数据包告诉服务端想要关闭连接,但是我们往往要考虑事情的最坏结果嘛,那就是服务端数据发了一半了,你想想前端的图片接收一半了会是什么效果,简直不能忍对不对!

第二步:服务端收到这个FIN包之后就知道客户端想要关闭连接了,但是自己有可能还有数据正传送呢,于是就采取一个折中策略。我先给你(客户端)一个信号(ACK包)告诉你我收到你的结束信息了,但是我可能还有数据没传完,你先等我一会吧。

第三步:客户端接收了这个ACK信息之后就知道服务端已经接到自己的FIN信息了,于是就进入了FIN_WAIT状态了,等啊等啊。。终于等到你,还好我没放弃,在最美的年纪。。。。终于等来了服务端发送的结束信息(FIN),现在客户端已经知道服务端已经做好关闭的准备了,自己也准备好了,那就可以关闭了吧。。。。等等,客户端知道服务器做好准备了,但是服务端怎么知道这次发送的FIN包被客户端接收到了,万一中间刮台风了吹走了呢。。于是就有了第四次握手:

第四步;客户端给服务端发送一个ACK信号告诉他“我客户端已经收到了,咱们可以分手了”。然后就进入了TIME_WITE状态了,如果服务端没有收到这个ACK可以再传嘛。当服务端收到这个ACK之后就知道可以断开了,当客户端等了2MSL后依然没有收到回复就证明服务端已经关闭了,于是乎自己也就关闭了。就这样,一段佳话就这么隆重的结束了。。。好忧桑。。。

整个过程的状态图如下:

客户端

服务端:

【注意】 在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同 步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你 发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。

阅读更多

没有更多推荐了,返回首页