对TCP三次握手、四次挥手以及TCP事务协议的理解

建立TCP需要三次握手才能建立,而断开连接则需要四次握手。整个过程如下图所示:

先来看看如何建立连接的。


首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。

那如何断开连接呢?简单的过程如下:


【注意】中断连接端可以是Client端,也可以是Server端。

假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

整个过程Client端所经历的状态如下:


而Server端所经历的过程如下:转载请注明:blog.csdn.net/whuslei


【注意】 在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报文。



看了《TCP详解卷3》第4章后,对TCP三次握手、四次挥手以及TCP事务协议有了更深层次的理解,下面就简单谈一谈。

首先是TCP连接的建立为什么要经过三次握手。RFC 793对此做了一个简单的说明:“引入三次握手”的主要原因是为了避免过时的重复连接再次建立时造成的混乱。为此,专门定义了一个特殊的控制报文RESET来解决这个问题“。怎么理解呢?举个例子,客户端在某时刻发服务端发起了一个连接请求,即一个SYN包。该SYN包由于某些原因未能在连接建立超时时间内到服务端,这时候客户端就会放弃建立连接,并且释放与该连接所有的数据结构。注意,上述SYN包虽然未能在连接建立时时间内到达服务端,但是它没有丢失,并且最终能在其生存时间内到达了服务端,这时候服务端到就发回一个ACK到客户端。客户端收到这个ACK之后,找不到与该连接对应的数据结构,于是就会发送一个RESET给服务端,这时候服务端就知道前面收到的是一个过时的连接了。

接着再来看TCP连接断开时为什么需要四个包(四次挥手)而不是像连接建立时三个包即可完成。假设主动断开连接的客户端(由于TCP是全双工的,服务端主动断开连接的情况也适合以下的讨论)。服务端收到客户端发送过来的FIN包后,不能马上就断开连接,因为它可能还没有把之前收到的数据交给应用程序处理。因此,服务端就需要等一会再通知客户端断开连接。这一段等待的时间,就是为了确保之前所有收到的都已经交给应用程序处理。也正是由于这段等待时间,使得服务端要主动向客户端发送一个FIN包来告之连接可以断开了。由于在TCP中,每收到对端的一个数据包(除不带数据的ACK外)都需要确认,因此服务端在收到客户端发出的FIN包后,需要马上发送一个ACK包,不然的话,客户端就会认为它发出的FIN包丢失了(于是就会重传)。因此,与TCP连接建立相比,TCP连接断开多出来的一个包就是服务端为了保证所有收到的数据都已经交给应用程序处理而发出的那个FIN包。也正是由于多了这个包,客户端在断开连接时引入了一个FIN_WAIT_2的状态。

在TCP四次挥手断开连接的过程中,主动断开连接的一方在收到对端发送过来的FIN包后,要进入一个TIME_WAIT状态,时间为两倍数据在网络中的最大生存时间(2MSL),之后才可以释放连接相关的所有数据结构。这样做有两个原因。第一个原因是主动断开连接的一方在收到对端发送过来的FIN包后,会给对端发送一个ACK包。但是这个ACK包可能会丢失,这时候对端就会重新发送一个FIN包过来。如果这时候在主动断开连接的一端已经释放所有连接相关的数据结构,那么显然就无法对该重新发送过来的FIN包进行处理了。第二个原因是如果不经过TIME_WAIT状态而直接释放所有连接相关的数据结构,那么就意味着该连接的IP和端口可以复用来建立一个新的连接。假设这个新的连接的对端也复用了之前的IP和端口。这时候就会出现一个微妙的情况:旧的连接的包由于某些原因还在网络中,并且能够在其生存时间内到达对端,那么对端就无法区分这是一个旧连接的包,还是新连接的包。有了这个持续时间为2MSL的TIME_WAIT状态,就可以保证旧连接的包一定不能在其生存时间内到达对端,于是对端就确信它收到的包都新连接的包了。

最后再来看TCP事务协议。TCP事务协议的最大好处有两个。第一个是避免每次建立连接时都要进行三次握手。第二个是避免常规TCP的持续时间为2MSL的TIME_WAIT状态(意味着相应的内存不能被及时释放)。TCP事务协议是如何做到的,这里就不展开讲了,具体可以读一下《TCP详解卷3》这本书。这里想要说的是,TCP事务协议获得的好处不是免费的,因为它需要增加一个称为连接计数器(CC)的开销。一方面是连接两方需要在内核中维护连接计数器相关的变量,另一方面是连接计数器的相关信息需要以TCP选项的形式携带在数据包中。不过,这又是典型的以空间换时间获得好处的做法。由此可见,以空间换时间的思想在计算机系统中是无处不在的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值