有限状态机 多图详解TCP三次握手和四次挥手( 四 )


FIN_WAIT_2 状态这就是著名的半关闭的状态了,这是在关闭连接时,客户端和服务器两次握手之后的状态 。在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种可能是,客户端一直处于 FIN_WAIT_2 状态,而服务器则一直处于 WAIT_CLOSE 状态,而直到应用层来决定关闭这个状态 。
RST,同时打开和同时关闭RST 是另一种关闭连接的方式,应用程序应该可以判断 RST 包的真实性,即是否为异常中止 。而同时打开和同时关闭则是两种特殊的 TCP 状态,发生的概率很小 。
常见面试题【问题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 报文 。在 Client 发送出最后的 ACK 回复,但该 ACK 可能丢失 。Server 如果没有收到 ACK,将不断重复发送 FIN 片段 。所以 Client 不能立即关闭,它必须确认 Server 接收到了该ACK 。Client 会在发送出ACK 之后进入到 TIME_WAIT 状态 。Client 会设置一个计时器,等待 2MSL 的时间 。如果在该时间内再次收到FIN,那么 Client 会重发 ACK 并再次等待2 MSL 。所谓的 2 MSL 是两倍的 MSL(Maximum Segment Lifetime) 。MSL 指一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间 。如果直到 2 MSL,Client 都没有再次收到 FIN,那么 Client 推断 ACK 已经被成功接收,则结束 TCP 连接 。
【问题3】为什么不能用两次握手进行连接?3 次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认 。
现在把三次握手改成仅需要两次握手,死锁是可能发生的 。作为例子,考虑计算机 S 和 C 之间的通信,假定 C 给 S 发送一个连接请求分组,S 收到了这个分组,并发 送了确认应答分组 。按照两次握手的协定,S 认为连接已经成功地建立了,可以开始发送数据分组 。可是,C 在 S 的应答分组在传输中被丢失的情况下,将不知道 S 是否已准备好,不知道 S 建立什么样的序列号,C 甚至怀疑 S 是否收到自己的连接请求分组 。在这种情况下,C 认为连接还未建立成功,将忽略 S 发来的任何数据分组,只等待连接确认应答分组 。而 S 在发出的分组超时后,重复发送同样的分组 。这样就形成了死锁 。
【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?TCP 还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源 。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为 2 小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔 75 秒钟发送一次 。若一连发送 10 个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接
树林美丽、幽暗而深邃,但我有诺言尚待实现,还要奔行百里方可沉睡 。-- 罗伯特·弗罗斯特
来源:https://www.cnblogs.com/huansky/p/13951567.html




推荐阅读