(18)TCP连接的建立与终止
一、建立连接协议
TCP的连接建立时间序列如下所示:
为了建立一个TCP连接:
(1)请求端(通常为客户端)发送一个SYN段指明客户打算连接的服务器端口以及初始序号ISN。这个SYN段为报文段1;
(2)服务器回送包含服务器初始序号的SYN报文段(报文段2)作为应答。同事将确认序号设置为客户的ISN+1以对客户的SYN报文段进行确认。一个SYN将占用一个序号。
(3)客户必须将确认序号设置为服务器的ISN+1以对服务器的SYN报文段进行确认(报文段3)。
这三个报文段完成连接的建立,称为三次握手(three-way handshake)。
二、连接终止协议
建立一个连接需要三次握手,而终止一个连接要经过四次握手。
(1)首先进行关闭的一方发送第一个FIN(报文段4),并执行主动关闭,另一方执行被动关闭。
(2)当服务器收到一个FIN,它会送一个ACK,确认序号为收到的序号+1(报文段5),和SYN一样,FIN将占用一个序号;
(3)同时TCP向应用程序发送一个文件结束符(EOF),接着这个服务器就关闭它的连接,导致它的TCP端发送一个FIN(报文段6);
(4)客户端必须回送一个确认ACK,确认序号设置为收到的序号+1(报文段7)。
连接终止过程如下图所示:
三、连接建立超时
建立一个连接的最长时间限制一般为75秒。
TCP软件采用一种500ms的定时器,初始连接中建立一个6秒的定时器(12个时钟滴答),当滴答计数器为0时,6秒定时器超时,这个定时器会在以后的24秒(48个滴答) 重新复位。之后的下一个定时器将接近24秒,因为当TCP的500ms定时器被内核调整时,它就被修改一次。
四、最大报文段长度
最大报文段长度(MSS)表示TCP传往另一端的最大块数据的长度。当建立连接时,连接双方都要通告各自的MSS。MSS选项只能出现在SYN报文段中。如果一方不接受另一方的MSS,则MSS就定位默认值536字节(这个默认值允许20字节的IP首部和20字节的TCP首部以适合576字节IP数据报)。
一般来说,如果没有分段发生,MSS越大越好。当TCP发送一个SYN时,或者因为一个本地应用进程想发起一个连接,或因为另一端的主机接收到一个连接请求,它能将MSS值设置为外出接口上的MTU长度减去固定的IP首部和TCP首部长度。对于以太网,MSS值可达1460。若目的IP地址为“非本地(nonlocal)”的,MSS通常的默认值为536。
五、TCP的半关闭
TCP提供了连接的一段在结束它的发送后还能接收来自另一端数据的能力,这就是所谓的半关闭。即一段发送FIN后,还可接收数据,直到收到另一端发送的FIN为止。如下图所示:
六、TCP的状态迁移图
TCP的状态迁移图如下所示:
TCP正常连接和终止所对应的状态如下所示:
七、2MSL等待状态
TIME_WAIT状态也称为2MSL等待状态。每个TCP必须选择一个报文段最大生存时间(MSL)。它是任何报文段被丢弃前在网络的最长时间。
处理原则:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2MSL。这样可以让TCP再次发送最后的ACK以避免这个ACK丢失(另一端超时并重发最后的FIN)。这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(socket)不能被使用。
总结起来,TIME_WAIT状态的主要作用包括:
1、保证全双工通信可靠关闭:如果不设置TIME_WAIT状态,直接设置成CLOSED状态,那么服务器得不到回复,会一直发送FIN给客户端。
2、允许老的重复分节在网络中消逝。TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个 原来的迷途分节就称为lost duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身 (incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情 况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时 候,来自连接先前化身的重复分组已经在网络中消逝。
八、平静时间的概念
TCP在重启的MSL秒内不能建立任何连接,这就是平静时间。
九、FIN_WAIT_2状态
在FIN_WAIT_2状态我们已经发出了FIN,并且另一端也对它进行了确认。只有另一端的进程完成了这个关闭(向本段发送FIN),我们这端才会从FIN_WAIT_2状态进入TIME_WAIT状态。这意味着我们这端可能永远保持这个状态,另一端也将处于CLOSE_WAIT状态,并一直保持这个状态直到应用层决定进行关闭。
十、复位报文段
TCP首部的RST位是用于复位的。一般,无论何时一个报文端发往相关的连接出现错误,TCP都会发出一个复位报文段。主要情况包括(1)到不存在的端口的连接请求;(2)异常终止一个连接。
异常终止一个连接对应用程序来说有两个优点:(1)丢弃任何待发数据并立即发送复位报文段;(2)RST的接收方会区分另一端执行的是异常关闭还是正常关闭。应用程序使用的API必须提供产生异常关闭而不是正常关闭的手段。
RST报文段不会导致另一端产生任何影响,另一端根本不进行确认,收到RST的一方将终止该连接,并通知应用层连接复位。
十一、检测半打开连接
如果一方已经关闭或异常终止连接而另一方却不知道,我们将这样的TCP连接称为半打开(Half-Open)的。半打开连接状态下,正常一方在收到异常一方(正常一方可能还不知道和对方建立了连接)的数据后会回送RST。
十二、同时打开
为了处理同时打开,对于同时打开它仅建立一条连接而不是两条连接。两端几乎在同时发送SYN,并进入SYN_SENT状态。当每一端收到SYN时,状态变为SYN_RCVD,同时他们都再发SYN并对收到的SYN进行确认。当双方都收到SYN及相应的ACK时,状态都变为ESTABLISHED。一个同时打开的连接需要交换4个报文段,比正常的三次握手多了一次。 具体过程如下所示:
十三、同时关闭
当应用层发出关闭命令,两端均从ESTABLISHED变为FIN_WAIT_1。这将导致双方各发送一个FIN,两个FIN经过网络传送后分别到达另一端。收到FIN后,状态由FIN_WAIT_1变为CLOSING,并发送最后的ACK。当收到最后的ACK,状态变为TIME_WAIT。同时关闭和正常关闭的段减缓数目相同。具体过程如下所示:
十四、TCP选项
每个选项的开始是1字节的kind字段,说明选项的类型。 Kind=0:选项表结束(1字节) Kind=1:无操作(1字节) Kind=2:最大报文段长度(4字节) Kind=3:窗口扩大因子(4字节) Kind=8:时间戳(10字节)。如下图所示:
十五、TCP服务器的设计
TCP服务器的端口号对于客户端是熟知的,且是固定的,服务器通过不同的客户端IP、端口号、服务器IP、端口号进行区分。
TCP服务器可以限定本地的IP地址使得只有服务器指定的本地IP地址的连接请求可以被内核中的TCP模块接收。而TCP服务器不能限定远端的IP地址和端口号。
十六、呼入连接请求队列
TCP在应用程序未接受已经经过三次握手完成连接操作的前,这些新的连接将在连接队列中排队等候,直到服务器的已经准备好接收数据了,服务器的TCP就会将接受的连接从该队列中移除,而在那之前发送的相关连接上的数据将被放入数据的缓冲队列中。
当队列已满时,TCP将不理会传入的SYN,也不发回RST作为应答。而由于不应答SYN,服务器程序迫使客户TCP随后重传SYN,以等待连接队列有空间接受新的连接。
一个TCP 连接由4个元组唯一确定:本地IP地址、本地端口号、远端IP地址和远端端口号。无论何时关闭一个连接,一端必须保持这个连接,我们看到TIME_WAIT状态将处理这个问题。处理原则是执行主动打开的一端在进入这个状态时要保持的时间为TCP实现中规定的MSL值的两倍。