TCP连接的建立与终止
引言
TCP是一个面向连接的协议。无论哪一方向向另一方发送数据之前,都必须现在双方之间建立一条连接。
UDP是无连接协议。
连接的建立与终止
建立过程(三次握手):
- 客户发送一个SYN(一个同步标志,建立连接时使用)段,指明打算连接的服务器的端口,以及初始序号(ISN)。该报文还包括了win(通知窗口大小)、mss(最大报文段长度)。
- 服务器发回包含服务器初始序号的SYN报文段,同时将确认序号(ACK)设置为客户的ISN+1,表示期望得到ISN+1的报文段。
- 将确认序号置为ISN+1,发送给服务器。
发送第一个SYN的一端成为主动打开,接受这个SYN并发回下一个SYN的一端执行被动打开。
当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号ISN。ISN随着时间变化而变化,所以每个连接的ISN都是不同的。
终止过程(四次握手):
建立连接的时候发送SYN,终止连接的时候发送FIN。发送FIN通常是应用层进行关闭的结果。
发送FIN的一端没有数据流动,但是一个TCP连接在收到一个FIN后仍能发送数据。(半关闭 half close)
- 首先主动关闭的一方发送一个FIN。
- 另一方收到这个FIN,执行被动关闭。发回一个ACK,确认序号+1.
- 服务器向应用程序传送一个文件结束符,接着这个服务器程序就关闭连接,导致服务器发送一个FIN。
- 客户收到FIN,返回一个ACK给服务器。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。
一般而言,一方完成主动关闭,另一方完成被动关闭。
也有情况为双方主动打开,或双方主动关闭的。
最大报文段长度MSS
MSS表示TCP传往另一端的最大数据块的长度。
- 当一个连接建立时,连接的双方都要通告各自的MSS。如果一方不接受
- 另一方的MSS值,则MSS就定为默认的536字节(因为主机要求IP数据报不能超过576字节,576-40首部长度=536)
- 对于一个以太网来说,MSS值可以达到1460字节。(因为以太网MTU为1500,除去40首部剩下1460)
- 如果目的IP地址是“非本地的”,那么MSS通常为536.(在传输过程中避免分片)
TCP的半关闭
TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。(少用)
发送了FIN的一方停止发送数据,但是还没收到另一个FIN之前,还是能接收数据。
TCP的状态变迁图
2MSL等待状态
TIME_WAIT状态也成为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。
当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失。
而且在2MSL期间,这个TCP连接的插口不能再被使用。只能在2MSL过去之后才能再被使用。此时任何迟到的报文段将被丢弃。(如果我们关闭一个客户程序,并马上重启,那么这个程序将不能重用相同的本地端口,但是客户程序一般不关心本地端口;但是服务器就不一样了,服务器一般都是用固定端口对应固定的服务,立即重启服务器的话就不能用这个熟知端口了,所以重启服务器程序之前,一般需要1~4分钟)。
于是给出了一个“平静时间”的概念,在重启动后的MSL秒内不能建立任何连接,这就成为平静时间。
FIN_WAIT_2状态
客户端发送一个FIN,并且收到ACK之后的状态。它将在接收到服务器端发送的FIN后进入TIME_WAIT状态。
如果另一端一直处于CLOSE_WAIT状态,不发送FIN,这意味着我们这端可能永远保持这个状态(半关闭)。
复位报文段
RST比特是用于“复位”的。
无论何时一个发往目的地的报文段出错,TCP都会发出一个复位报文段。
到不存在的端口的连接请求
在UDP中,一个数据报达到目的端口时,该端口没在使用,它将产生一个ICMP端口不可达的信息。而TCP则使用复位。
异常终止一个连接
发送FIN终止连接的方式叫做有序释放。
中途发送一个复位报文段来释放一个连接,叫做“异常”释放。
异常终止一个连接对应用程序来说有两个优点:
- 丢弃任何待发数据并立即发送复位报文段;
- RST的接收方会区分另一端执行的是异常关闭还是正常关闭。应用程序使用的API必须提供产生异常关闭而不是正常关闭的手段。
需要注意的是RST报文段不会导致另一端产生任何响应,另一端根本不进行确认。收到RST的一方将终止该连接,并通知应用层连接复位。
检测半打开连接
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的TCP连接成为半打开的。只要不打算在半打开的连接上传输数据,仍除去连接状态的一方就不会检测另一方已经出现异常。
半打开连接的另一个常见原因是当服务器主机突然掉电而不是正常的结束服务应用程序后再关机,服务器主机重启后,从客户向服务器发送另一行字符。由于服务器的TCP已经重新启动,它将丢失复位前连接的所有信息,因此它不知道数据报文段中提到的连接。TCP的处理原则是接收方以复位作为应答。
同时打开与同时关闭
很少用到,发生的概率很小。