TCP断开那些事

继上一篇后,我们再来看一下四次挥手的过程


这里其实没有必要过多阐述,一张图胜过千言万语。

与三次握手一样,四次挥手的过程中也有许多扩展问题。

当然问的最多的还是:为什么要四次握手?为什么要等待2MSL的时间?

这个问题没必要死记硬背,只需要了解全双工的工作机制就好。

至于等待的2MSL(报文最大生存时间),一是保证传输的信息已经到达,二是防止无法收到确认报文段而不能进入CLOSED状态。

其他的扩展问题,只要想明白原理也很容易理解,比如:

1、两边同时断开TCP连接?

仍然是要四次挥手的。以下是RFC-793的说法:

    A simultaneous CLOSE by users at both ends of a connection causes
    FIN segments to be exchanged.  When all segments preceding the FINs
    have been processed and acknowledged, each TCP can ACK the FIN it
    has received.  Both will, upon receiving these ACKs, delete the
    connection.

2、二三次挥手能否合一?

可以。首先两个标志位FIN、ACK可以同时置为1,然后服务端收到断开请求时刚好没有数据可以传递,就可以合一。

如果还有数据,那就不能合一。

3、TIME_WAIT的问题?

短时间内关闭大量连接的化,必然出现大量TIME_WAIT状态的连接。这消耗了服务器的资源。

更重要的是它会占用客户端的本地端口和服务器的熟知端口。

大多数T C P实现(如伯克利版)强加了更为严格的限制。在2 M S L等待期间,
插口中使用的本地端口在默认情况下不能再被使用。

在连接处于2 M S L等待时,任何迟到的报文段将被丢弃。因为处于2 M S L等待的、由该插
口对(socket pair)定义的连接在这段时间内不能被再用,因此当要建立一个有效的连接时,来
自该连接的一个较早替身( i n c a r n a t i o n)的迟到报文段作为新连接的一部分不可能不被曲解

因此Linux提供了快速回收的机制。为了使得这个机制在不用TIME_WAIT的情况下安全运行,有些连接会被拒绝。

Linux同样提供了它的重用机制,具体可见https://studygolang.com/articles/10613

4、没有正常关闭?

客户端和服务端并不会使用应用级的定时器检测对方的活动状态,保活并不是TCP规范中的一部分。

但它仍然十分有用,以下是一个例子:

如果一个给定的连接在两个小时之内没有任何动作,则服务器就向客户发送一个探查报
文段(我们将在随后的例子中看到这个探查报文段看起来像什么)。客户主机必须处于以下4
个状态之一。
1) 客户主机依然正常运行,并从服务器可达。客户的T C P响应正常,而服务器也知道对
方是正常工作的。服务器在两小时以后将保活定时器复位。如果在两个小时定时器到时间之
前有应用程序的通信量通过此连接,则定时器在交换数据后的未来2小时再复位。
2) 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的T C P都
没有响应。服务器将不能够收到对探查的响应,并在7 5秒后超时。服务器总共发送1 0个这样
的探查,每个间隔7 5秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止
连接。
3) 客户主机崩溃并已经重新启动。这时服务器将收到一个对其保活探查的响应,但是这
个响应是一个复位,使得服务器终止这个连接。
4) 客户主机正常运行,但是从服务器不可达。这与状态2相同,因为T C P不能够区分状态
4与状态2之间的区别,它所能发现的就是没有收到探查的响应。
服务器不用关注客户主机被关闭和重新启动的情况(这指的是一个操作员的关闭,而不
是主机崩溃)。当系统被操作员关闭时,所有的应用进程也被终止(也就是客户进程),这会
使客户的T C P在连接上发出一个F I N。接收到F I N将使服务器的T C P向服务器进程报告文件结
束,使服务器可以检测到这个情况。

现在,可以回到那张经典的TCP状态变迁图,回想TCP连接和断开的细节了。

注:

本文主要引自《TCP/IP详解 卷一:协议》,部分内容源于网上。

如有侵权,请告知。

猜你喜欢

转载自www.cnblogs.com/sh1296/p/10778656.html