TCP是面向连接的传输层协议。在每一次数据传输之前首先要在通信双方建立一条连接,即在源进程和目的进程之间建立一条虚路径。属于同一个报文的所有报文段都通过这条虚路径传输,数据传输完成后释放连接。在TCP中面向连接的传输是通过两个过程来完成的:建立连接和释放连接。连接管理就是使连接的建立和释放都能正常进行。
TCP连接的建立和释放都是采用客户-服务器模式。主动发起连接建立的进程称为客户进程,而另一个被动等待连接建立的进程被称为服务器进程。
TCP以全双工方式传送数据。在任何数据传送之前,要使每一方能确知对方的存在。双方都必须对通信进行初始化,并得到对方的认可。当两个TCP建立连接后,它们就能够同时互相发送报文段。
TCP中建立连接采用3次握手(Three-Way Handshake)的方式实现。建立连接的过程从服务器开始。服务器进程先发出一个被动打开的命令,告诉它的TCP它已准备好接受客户进程连接请求,即被动的等待握手。客户应用进程发出主动打开命令,表明要与一个服务器应用进程使用传输层协议中的TCP建立传输连接,即发出建立连接请求。TCP建立连接3次握手的过程如图 8-6 所示。
3次握手的步骤如下:
1)客户端发送第一个报文段,即SYN报文段。SYN报文段指明这个客户打算连接的服务器的端口,以及客户初始序号,ISN(假设x=1200),用来对从客户端发送到服务器端的数据字节 进行编号,表明当从客户端向服务器端发送数据时第一个数据字节的序号就是1200。若客户打算在这个报文段中增加相应的选项,就可在此进行定义。如定义从服务器接收的 MSS。
这个SYN报文段为报文段1。报文段1把同步位SYN标志置1,确认位ACK标志置为0,定义这个客户端打算建立一条具有某些参数的连接的愿望。
2)如果服务器端同意接受连接,则发回报文段2.即使用SYN位和ACK位作为应答来回应客户端这个建立连接的请求。它将客户端的初始序号加1(即ACK=x+1=1201)以对客户的SYN报文段进行确认。同时,选择服务器端的初始序号(假设y=4800),用来对从服务器端发送到客户端的数据字节进行编号,那么从服务器端向客户端发送数据时第一个数据字节的序号是4800。如果需要的话,可在报文段中增加相应的选项,如服务器端所定义的MSS(定义从客户端接收的MSS)。
报文段2中确认位ACK标志为1,同步位SYN标志为1,所以也称这个报文段2为SYN+ACK报文段。
一个 SYN 将占用一个序号。
3)最后,客户端发送报文段3。这是一个确认报文段。它使用ACK标志和确认号字段来确认收到了报文段2。确认号字段为服务器的初始序号加1(即y+1=4801)以对服务器端的SYN报文段进行确认。
运行客户进程的主机A的TCP通知其上层应用进程连接已建立;运行服务器进程的主机B在收到这个确认之后,表示连接建立,也通知其上层应用进程。这时就可以开始发送和接收数据了。
在报文段3中把确认位ACK标志置为1,同步位SYN标志置为0。这仅仅是一个ACK报文段。
这3个报文段的交换过程,即3次握手过程完成了TCP连接的建立。
在TCP连接的建立过程中,发送第1个SYN的一端将执行主动打开,接收这个SYN并发回下一个SYN的另一端执行被动打开。
如果两个主机同时都发出主动打开,企图在相同的两个套接字之间建立一条连接则发生连接请求碰撞,如图 8-7 所示。
在这种情况下,两个TCP都向对方发送SYN+ACK报文段,然后在这两方之间建立一条连接。即这个时候仅有一条连接建立起来,而不是两条连接。因为所有的连接都是由它们的端点来惟一标识的。
在数据传输结束后,通信的双方都可以发出释放连接的请求。
一个TCP连接是全双工的(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。原则就是当一方没有数据发送后就发送一个终止位FIN来终止这个方向的连接。TCP连接的释放是通过通信的两方都发送一个FIN标志为1的TCP报文段来实现的。当一个FIN报文段被确认后,那个方向的连接就被关闭。也就是说收到一个FIN只意味着在这一方向上没有数据传送了,但它仍然可以继续接收对方发来的数据。只有当两个方向的连接都被关闭后,该TCP连接才被完全释放。所以要释放一个连接需要4个TCP报文段的交互,称为4次握手,如图8-8所示。
TCP连接释放4次握手的步骤如下:
1)首先进行关闭的客户端TCP发送第一个报文段(报文段1),即FIN报文段,终止位FIN标志置1。执行主动关闭,不再发送数据。设报文段1中的序号SEQ=x=2500。
2)服务器端TCP发送第二个报文段(报文段2),即ACK报文段,用来确认从客户发来的FIN报文段。这个确认号等于收到的FIN报文段中的序号加1,即ACK=2501,并设其序号SEQ=y=7000。
3)服务器端TCP可以继续在从服务器端到客户端的方向上发送数据,当服务器端没有数据发送时,它就发送第三个报文段(报文段3),即 FIN 报文段,终止位 FIN 标志置1。关闭从服务器到客户的数据传送。报文段3的SEQ=y+1=7001、ACK=x+1=2501。
4)客户端TCP发送第4个报文段(报文段4),即 ACK 报文段,用来确认从服务器端TCP收到了 FIN 报文段。这个确认号等于从服务器收到的 FIN报文段的序号加1,即 ACK=7002、SEQ=x+1=2501。
至此,整个连接已经全部释放。
一个 FIN 将占用一个序号。
一个TCP连接的两端,也可能会同时发送FIN报文段,都执行主动关闭。TCP允许这样的同时关闭。这两个报文段按常规的方法被确认,然后连接被释放。这和两台主机按顺序先后释放连接没有本质区别。
TCP连接通常是由客户端发起的。这样,第一个SYN从客户端传到服务器端。然而,一个TCP连接的每一端都能主动关闭这个连接,即都能首先发送FIN。一般情况下是客户应用进程打算终止连接(但不总是),因为客户应用进程通常由用户控制。
TCP首部中的RST位是用于复位的。当TCP需要复位连接时则使用RST报文段。
TCP可以请求把一个连接复位。连接复位表示当前的连接已经被撤销。以下是发生复位的3种情况:
1)一端的TCP请求连接到并不存在的端口,另一端的TCP就可以发送一个复位报文段,其复位位RST置1,来取消这个请求。
2)一端的TCP出现了异常情况,而愿意把连接异常终止。它就可以发送复位报文段,其复位位RST置1,来关闭这一连接。
3)一端的TCP可能发现在另一端的TCP已经空闲了很长的时间,则它可以把这个连接撤销。它就可以发送复位报文段,其复位位RST置1,来撤销这个连接。
复位报文段不会导致另一端产生任何响应,另一端也不需进行确认。收到RST的一方将终止这个连接,并通知应用层连接复位。连接复位是一种立即的异常终止,这意味着在两个方向的数据传输都立即停止。