TCP连接的建立和终止
UDP向另一端发生数据报时,无需任何提前的握手。而TCP必须在双方之间建立一条连接。
建立连接协议
为了建立一条TCP连接,三次握手。
-
客户端发送一个SYN段指明客户打算连接的服务器的端口,以及初始序号(ISN)。
-
服务器发回包含服务器的初始序号的SYN报文段作为应答。同时,将确认序号设置为客户的ISN+1以对客户的SYN报文段进行确认。
-
客户将确认序号设置为服务器的ISN+1以对服务器的SYN报文段进行确认。
ISN随时间而变化,因此每个连接都将具有不同的ISN。
连接终止协议
终止一个连接需要4次握手,这是由于TCP的半关闭造成的。因为TCP连接是全双工的,那么每个方向必须单独地进行关闭。当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。
收到一个FIN只意味着在这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。
2.19.39.png最大报文段长度
MSS表示TCP传往另一端的最大块数据的长度。当建立一个连接时,每一方都有用于通告它期望接收的MSS选项。如果一方不接受来自另一方的MSS值,则MSS就定为默认值536字节。当TCP发送一个SYN时,它能将MSS的值设置为外出接口上的MTU长度减去固定的IP首部和TCP首部长度。
MSS让主机限制另一端发生数据报的长度,主机也能控制它发送数据报的长度,着将使以较小的MTU连接到一个网络上的主机避免分段。
TCP的半关闭
半关闭:TCP连接的一端在结束它的发送后还能接收来自另一端数据的能力。
2.32.47.png
TCP的状态变迁图
2.39.30.png2.40.33.png
2MSL等待状态
TIME_WAIT状态也称为2MSL等待状态。每个具体的TCP实现必须选择一个报文段最大生存时间MSL(报文段被丢弃前在网络的最长时间,这个时间是有限的,因为IP数据报有限制其生存时间的TTL字段)。MSL常用的值是30s,1min,2min。
当一方执行主动关闭后并发回最后的一个ACK报文后,该TCP连接在TIME_WAIT状态停留的时间为2倍的MSL。这样可防止最后发送的这个ACK丢失,导致另一端超时重发最后的FIN。同时造成的另一个结果是,这个TCP连接在2MSL等待时间内,定义这个连接的四元组(客户IP端口,服务器IP端口)不能再使用,只有在2MSL结束后才能被使用。且当连接处于2MSL等待时,任何迟到的报文段将被丢弃。
复位报文段
TCP首部的RST比特是用于“复位”的。当一个连接请求到达时,目的端口没有进程在听,对于UDP会产生一个ICMP端口不可达信息。而TCP则使用复位。
异常终止一个连接
异常释放:发送一个复位报文段而不是FIN来中途释放一个连接。
异常终止有两个优点:
-
丢弃任何待发送数据并立即发送复位报文段
-
RST的接收方会区分另一端执行的是异常关闭还是正常关闭。
RST报文段不会导致另一端产生任何响应,另一端根本不进行确认,收到
RST的一方马上终止连接,并通知应用层连接复位。
检测半打开连接
如果一方已经关闭或异常终止连接而另一方还不知道,那这个TCP连接就是半打开的。
例如关闭客户端的电源,服务器不知道客户端已经消失了,之后又重新开启客户端,那么服务器上又会启动一个新的服务器程序。这样就会导致服务器主机上产生许多半打开的TCP连接。(可以通过keepalive检查)
同时打开
存在两个程序同时彼此执行主动打开的情况。对于同时打开,TCP仅建立一条连接。一个同时打开的连接需要交换4个报文段,比正常的多一个。且每一端即是客户也是服务器。
3.10.43.png
同时关闭
3.13.14.pngTCP服务器的设计
大多数TCP服务器进程是并发的。当一个新的连接请求到达服务器时,服务器接收这个请求,并调用一个新进程来处理这个新的客户请求。(当传入的连接请求到达并被接收时,系统内核中的TCP模块就创建一个处于ESTABLISHED状态的进程。)TCP使用四元组(客户IP端口,服务器IP端口)来处理传入的多个连接请求。因为仅凭端口号,TCP是无法确认哪个进程接收了连接请求。
一个并发服务器调用一个新的进程来处理每个客户请求,处于被动连接请求的服务器应该始终准备处理下一个呼入的连接请求。
当服务器正在创建一个新的进程或操作系统在忙于处理优先级更高的进程时,若到达了多个连接请求,TCP采用以下规则处理:
-
正等待连接请求的一端有一个固定长度的连接队列,该队列中的连接已经三次握手完成,但还没有被应用层所接受。(TCP接受一个连接是将该连接放入这个队列,而应用层接受连接是将其从该队列中移出。)
-
应用层将指明这个队列的最大长度,这个值通常是指积压值。
-
当一个新的连接请求(SYN)到达时,TCP使用一个算法,根据当前连接队列中的连接数来确定是否接受这个连接。对于新的连接请求,TCP监听的端点的连接队列中还有空间,TCP模块将对SYN进行确认并完成连接的建立。但应用层只有在三次握手中的第三个报文段收到后才会知道这个新连接。此外,当客户端进程主动打开成功但服务器还不知道这个新连接时,服务器的TCP仅将接受的数据放入缓冲队列。
-
如果连接队列中已经没有空间,那么TCP将不会处理收到的SYN,也不发回任何报文段(不发回RST)。若应用层不能及时接受已经被TCP接受的连接,这些连接会占满整个连接队列,客户的主动打开最后将超时(重传SYN,以等待连接队列有空间接受新的连接)。