为什么TCP连接需要三次握手和四次挥手、存在TIME_WAIT状态的两个理由

1、三次握手建立连接详解

三次握手的大致流程如下:

(1)客户端向服务器发送一个SYN J;

(2)服务器向客户端响应一个SYN K,并对SYN J 进行确认 ACK J+1;

(3)客户端再向服务器发送一个确认ACK K+1。

这样就完成了三次握手,但是这个三次握手发生在哪几个函数中呢?
在这里插入图片描述
从图中可以看出,服务器必须准备接受外来的连接。这通过socket、bind和listen函数来完成,称为被动打开。

客户端通过调用connect进行主动打开。这引起客户端向服务器发送了SYN J(表示同步,它告诉服务器客户将在连接中发送的数据的初始序列号)分节,这时connect进入阻塞状态。

服务器监听到连接请求,即收到SYN J分节,调用accept函数接受请求,并向客户端发送SYN K(它告诉客户端服务器将在连接中发送的数据的初始序列号)、ACK J+1 分节,这时accept进入阻塞状态。

客户端收到服务器的SYN K,ACK J+1 分节之后,这时connect返回,并对SYN K分节进行确认;服务器收到ACK K+1分节时,accept返回,至此三次握手完毕,连接建立。

总结:客户端的connect在三次握手的第二次返回,而服务器端的accept在三次握手的第三次返回。

2、四次挥手释放连接详解

建立一个连接需要三次握手,而终止一个连接要经过4次挥手。这由TCP的半关闭(half-close)造成的。既然一个TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。TCP的四次挥手释放连接的过程如下所示:
在这里插入图片描述
具体步骤:

1)某个应用进程首先调用close,我们称这一端执行主动关闭。这一端的TCP于是发送一个FIN分节,表示数据发送完毕;

2)另一端接受到FIN分节之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给接受端应用进程,因为FIN的接受意味着应用进程在相应的连接上再也接受不到额外数据;

3)一段时间之后,接受到文件结束符的应用进程调用close关闭它的套接口。这导致它的TCP也发送一个FIN;

4)接受到这个FIN的原发送TCP(即执行主动关闭的那一端)对它进行确认。

TCP关闭时,每一端都要发送一个FIN。这种情况除了在应用进程调用close时会发生,还会在进程终止时发生。进程终止包括自愿按(调用exit或者从main函数返回)、不自愿(进程收到一个终止本进程的信号)的情况,进程终止时所有打开的TCP连接上都会发出一个FIN。

当客户端应用程序主动请求关闭时, 调用close或shutdown关闭连接, 这时应用程序发送FIN肘,然后进入FIN_WAIT_l状态,等待服务器端发送确认包ACK,接受到服务器端的ACK 以后, 然后客户端进入FIN_WAIT_2状态, 等待服务器端调用close, 并发送FIN, 当客户端接受到FIN后, 发送ACK, 进入最终的TlME_WAIT状态。

**需要注意的是,执行主动关闭的那一端进入TIME_WAIT状态。**留在TIME_WAIT的持续的时间是MSL(最长分节生命周期)时间的两倍,也就是2MSL。MSL一般情况是30秒到2分钟,所以TIME_WAIT的时间一般为1~4分钟。
在这里插入图片描述

存在TIME_WAIT状态有两个理由:

1、实现终止TCP全双工连接的可靠性

**假设最终的ACK丢失,服务器将重发最终的FIN,因此客户必须维护状态信息以允许它重发最终的ACK,如果不维护状态信息,它将响应RST(复位连接,表示TCP连接中出现严重错误),而服务器则把该分节解释成一个错误。**如果TCP打算执行所有必要的工作以彻底终止某个连接上两个方向的数据流,那么它必须能够处理连接终止序列四个字节中任何一个分节丢失的情况,也即主动关闭的那一端必须进入TIME_WAIT状态,因为它可能不得不重发最终的ACK。

2、允许老的重复分节在网络中消失

TCP 不能给处于TlME_WAIT状态的连接启动新的化身, 既然TIME_WAIT状态的持续时间是2MSL, 这就足够让某个方向上的分组最多存活MSL秒即被丢弃, 另一个方向上的应答最多存活MSL秒也被丢弃,通过实施这个规则,我们就能保证当成功建立一个TCP连接时,来自该连接先前的化身的老重复分组都已经在网络中消逝了。

问题1:TCP为何采用三次握手来建立连接,若采用二次握手可以吗,请说明原因?

不可以。采用三次握手是为了防止失效的连接请求报文突然又传送到服务器,从而发生错误。当客户端发出的连接请求报文段由于某些原因没有即时到达服务器,而客户端在等待一段时间后,又重新向服务器发送连接请求,且建立成功,顺序完成数据传输,那么第一次发送的连接请求报文段就称为失效的连接请求报文段。

考虑这样一种特殊情况,客户端第一次发送的连接请求并没有丢失,而是因为网络问题导致延迟到达服务器,服务器以为是客户端又发起的新的连接,于是服务器同意连接,并向客户端发回确认,但是此时客户端不予理会,服务器就一直等待客户端发送数据,导致服务器资源浪费。

问题2:TCP为何采用四次挥手来释放连接?

关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了,但未必你所有的数据都全部发送给对方了,所以你未必会马上关闭socket, 也即你可能还需要发送一些数据给对方之后,再发送 FIN报文给对方来表示你没有数据发送给对方了,针对每个FIN报文,都需要一次ack报文,故需要四次挥手。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值