TCP连接的建立、终止和状态转换

TCP连接的建立:

    下述步骤建立一个TCP连接:
    1.服务器必须准备好接受外来的连接。这通过调用socket、bind和listen函数来完成,称为被动打开(passive open)。
    2.客户通过调用connect进行主动打开(active open)。这引起客户TCP发送一个SYN分节(表示同步),它告诉服务器客户将在(待建立的)连接中发送的数据的初始序列号。一般情况下SYN分节不携带数据,它只含有一个IP头部、一个TCP共部及可能有的TCP选项。
    3.服务器必须确认客户的SYN.同时自己也得发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列号。服务器以单个分节向客户发送SYN和对客户SYN的ACK。
    4.客户必须确认服务器的SYN。

   连接建立过程至少需要交换三个分组,因此称之为TCP的三路握手(three-way handshake)

TCP连接的终止:

TCP用三个分节建立一个连接,终止一个连接则需四个分节。

    1.某个应用进程首先调用close,我们称这一端执行主动关闭(active close)。这一端的TCP于是发送一个FIN分节,表示数据发送完毕。
    2.接收到FIN的另一端拽行被动关闭(passive close)。这个FIN由TCP确认。它的接收也作为文件结束符传递给接收方应用进程(放在已排队等候该应用进程接收的任何其他数据之后),因为FIN的接收意味着应用进程在相应连接上再也接收不到额外数据。
    3.一段时间后,接收到文件结束符的应用进程将调用close关闭它的套接口。这导致它的TCP也发送一个FIN。
    4.接收到这个FIN的原发送方TCP(即执行主动关闭的那一端)对它进行确认。

    因为每个方向都需要有一个FIN和一个ACK,所以一般需要四个分节。我们使用限定词“一般”是因为:有时步骤1的FIN随数据一起发送;另外,执行被动关闭那一端的TCP在步骤2和3发出的ACK与FIN也可以合并成一个分节, 在步骤2与步骤3之间可以有从执行被动关闭端到执行主动关闭端的数据流。这称为半关闭(half-close).

套接口关闭时,每一端TCP都要发送一个FIN。这种情况在应用进程调用close对会发生,然而在进程终止时,所有打开的描述字将自愿(调用exit或从main函数返回)或不自愿(进程收到一个终止本进程的信号)地关闭,此时仍然打开的TCP连接上也会发出一个FIN。

TCP状态转换图:
TCP连接的建立和终止可以用状态转换图Cstate transition diagram)来说明。


    图中,为一个连接定义了11种状态,并且TCP规则决定如何从一个状态转换到另一个状态,这种转换基于当前状态及在该状态下所接收的分节。例如,当应用进程在CLOSED状态下执行一个主动打开时,TCP将发送一个SYN并从CLOSED状态转换成SYN_SENT状态。如果该TCP接着接收到一个附带ACK的SYN,它将发送一个ACK并转换成ES-TABLISHED状态。这个状态是数据传送状态。有两个外向箭头引导ESTABLISHED状态的连接终止处理。如果应用进程在接收到文件结束符前调用close(主动关闭),则转换成FIN_WAIT_1状态。如果在ESTABLISHED状态下应用进程接收到FIN,则转换成CIOSE_WAIT状态。
执行主动关闭的那一端进入TIME_WAIT状态,执行被动关闭的一端进入CLOSE_WAIT状态。


TIME_WAIT状态:

有关网络编程的TCP中最不容易理解的地方是它的TIME_WAIT状态。在图中我们看到执行主动关闭的那端进入这种状态。这个端点留在该状态的持续时间是最长分节生命期MSL (maximum segment lifetime)的两倍,有时称为2MSL。

存在TIME-WAIT状态有两个理由
    1.实现终止TCP全双工连接的可靠性
    2.允许老的重复分节在网络中消逝

    第一个理由:
    假设最终的响应ACK丢失,服务器将重发最终的FIN,因此客户必须维护状态信息以允许它重发最终的ACK。如果不维护状态信息,它将响应以RST(另外一个类型的TCP分节),而服务器则把该分节解释成一个错误。如果TCP打算执行所有必要的工作以彻底终止某个连接上两个方向的数据流(即全双工关闭),那么它必须正确处理连接终止序列四个分节中任何一个分节的丢失情况。本例子也说明执行主动关闭的一端为什么进入TIME_WAIT状态,因为它可能不得不重发最终的ACK。

     第二个理由:
     我们假设206. 62. 226. 33端口1500和198. 69.10.2端口21之间有一个TCP连接。我们关闭这个连接后,在以后某个时候又重新建立起相同的IP地址和端口之间的TCP连接。后一个连接称为前一个连接的化身(incar-nation).因为它们的IP地址和端口号都相同。TCP必须防止来自某个连接的老重复分组在连接终止后再现,从而被误解成属于同一连接的化身。要实现这种功能,TCP不能给处于TIME-WAIT状态的连接启动新的化身。既然TIME-WAIT状态的持续时间是2MLS,这就足够让某个方向上的分组最多存活MSL秒即被丢弃,另一个方向上的应答最多存活MSL秒也被丢弃。通过实施这个规则,我们就能保证当成功建立一个TCP连接时,来自该连接先前化身的老重复分组都已在网络中消逝。

原文地址:https://www.cnblogs.com/liujiahi/p/2196365.html