TCP作为传输层一个复杂的协议,它所有的控制,比如说可靠性传输、流量控制、拥塞控制都是建立在连接的基础之上。而连接的管理包括 连接的建立和连接的释放,也是通过TCP的报文传输来完成的。更具体的讲,是通过TCP首部当中的各个字段来实现连接的建立和释放的。
首先来看一下TCP连接的建立:
TCP是面向连接的协议。
传输连接有三个阶段:
① 连接建立
② 数据传送(建立连接成功之后,进行数据的双向传送)
③ 连接释放(数据传送完毕之后,再对连接进行释放操作 )
传输连接的管理就是使传输连接的建立和释放都能正常地进行。
在建立连接的过程当中,需要双方共同来解决三个问题:
① 首先,每一方要能够明确地知道对方的存在,确认双方的发送和接收功能是可以正常工作的。
② 第二要允许双方协商一些重要的参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等)。
③ 第三是需要双方对传输实体资源进行分配(如各自发送,接收缓存大小、连接表中的选项等)。
TCP连接的建立采用 客户机-服务器的方式:
主动发起连接建立的应用进程叫做客户;
被动等待连接建立的应用进程叫做服务器。
三次握手的过程:
TCP建立连接的过程叫做握手
握手需要在客户和服务器之间交换三个TCP报文段,称为三次握手
采用三次握手主要是为了防止已失效的连接请求报文段 突然又传送到了,因而产生错误。

首先A的TCP作为客户 向B发出连接请求的报文段,其中会把同步位SYN置为1,并选择序号seq=x,表明传送数据时第一个数据字节的序号是x:

B的TCP收到连接请求报文段之后,如果同意,则发回确认。B在确认的报文段当中,同样也设SYN同步位为1,同时把ACK确认位设为1,而确认号ack设置为x+1,表示之前x报文已经正确地收到,期待收到x+1序号的报文段。同时自己来选择序号seq设为y(x和y表明A、B双方各自发送的序号是独立的):

A在收到了确认报文段之后,还需要再一次给B发出确认,也就是对确认的确认,其中ACK确认位设为1,确认号ack设为y+1,同样表明之前 过来序号是y的报文已经正确地接收到了,至此三次握手的过程结束。
A的TCP会通知上层应用进程,现在连接已经建立了,我们双方可以由上层的应用进程把对应的数据传递给A或B的TCP来进行发送和处理。
注意 :其中第三次B对A的确认,需要由A再一次发送确认,也就是说对确认的再确认是非常必要的。主要是为了防止对已经失效的连接请求报文,突然又传到B所产生的错误。考虑这样一种情况:
比如说A的第一个连接报文,由于在某个站点滞留,B收到之后,会认为A又重新发了一次连接,这个时候B会发送确认报文,同意建立新的连接。而这个时候当A收到了确认连接的报文之后,由于这个确认实际上是对一个并不存在的连接请求来进行的确认,A不去理睬B的确认,而B如果没有对确认的再次确认,会误认为已经建立好了,等待A去发送数据,但这个时刻A并没有数据要发送,双方就进入到了一个误会的状态。所以第三次的握手,对确认的再确认实际上是非常必要的。
四次挥手的过程:
在连接建立成功之后,双方的数据传输结束之后,通信的双方都可以来释放连接。通过TCP的连接释放双方各自释放相应的资源。而TCP连接的释放过程,是通过四次挥手来完成的。

A的应用进程向它的TCP发出连接释放的报文段并停止再次发送数据,主动关闭TCP连接。这个时候A会把连接释放报文段的首部的FIN设为1,序号seq设为u,等待B的确认。实际上就是告诉B,我现在数据都发送完了,我需要把我发送数据的这个方向上的数据传输方向给关闭上:

B针对这个挥手的报文会发出确认,其中确认号ack设为u+1,表示之前你要进行连接释放的报文已经正确收到了。而报文段自己的序号seq设为v(u和v仍然是相互独立的),意味着B这个时刻不一定需要立刻去释放TCP的连接,因为它仍然有可能有数据要去发送:

这个时候,从A到B这个方向的连接就释放掉了,TCP连接是处于一个半关闭的状态(如果B仍然有数据要发送的时候,A仍然是需要接收的)在这个时刻,原来一条全双工的TCP连接,会变成一个半双工的TCP连接,也就是所谓的半关闭状态,B可以发送数据A可以接收数据。
- 当B把自己的数据发送完毕之后,没有要再向A发送的数据了,应用进程就可以通知TCP释放连接。释放连接报文的设置和A是类似的,仍需要把FIN的标志位设为1:

- A在收到连接释放报文段之后,必须发出确认。在报文段当中,设置ACK确认位设为1,确认号ack设为w+1(这个位置的w和之前B在收到对A的释放请求的v的序号是各自独立的)实际上是因为B在发送数据的过程当中,又消耗了一部分字节,所以w和v实际上是相互独立的。A在发送这个确认报文段当中,还会设置字节的序号seq为u+1(这个u和之前释放连接对应的u序号是完全一样的)

当A收到了释放请求之后,必须再经过两倍的MSL时间,才会真正的释放掉连接,此处的MSL指的是最长报文寿命。
之所以要设两倍的SML时间,主要是出于两方面的考虑:
第一是为了保证A发送的最后一个ACK报文段能够顺利地到达B。
第二是为了防止已失效的连接请求报文段,出现在本连接当中。假如A在发送完最后一个ACK报文段之后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现旧的连接请求报文段。实际上就是说,我们设一个足够长的时间,使得各种请求都在网络上消失掉,不至于当新的请求到达的时候引发误会。