1、概述
TCP提供一种面向连接的、可靠的字节流服务。全双工通信。一个TCP连接由一个4元组唯一确定:本地 IP地址、本地端口号、远端 IP地址和远端端口号。
TCP将用户数据打包构成报文段;它发送数据后启动一个定时器;另一端对收到的数据进行确认,对失序的数据重新排序,丢弃重复数据; TCP 提供端到端的流量控制,并计算和验证一个强制性的端到端检验和。
许多流行的应用程序如 Telnet, Rlogin, FTP,SMTP 都使用TCP。
TCP通过下列方式来提供可靠性:
(1)应用数据被分割成TCP认为最适合发送的数据块。这和UDP完全不同,应用程序产生的数据报长度将保持不变。由TCP传递给IP的信息单位称为报文段或段(segment)。
(2)当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
(3)当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。
(4)TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输 过程中的任何变化。如果收到段的检验和有差错, T P将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。
(5)既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。
(6) 既然I P数据报会发生重复, TCP的接收端必须丢弃重复的数据。
(7)TCP还能提供流量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。
总结:TCP中保持可靠性的方式就是超时重发。只要不得到确认,就重新发送数据报,直到得到对方的确认为止。
2、TCP的首部
TCP数据被封装在一个 IP 数据报中,如图:
下图为TCP首部的数据格式。如果不计任选字段,它通常是20个字节。
(1)源端口和目的端口:用于寻找发端和收端应用进程。这两个值加
上I P首部中的源端I P地址和目的端I P 地址唯一确定一个 T C P连接。(2)接口,运输层的复用和分解功能都要通过端口才能实现。
(3)序号:标识从T C P发端向T C P收端发送的数据字节流。占4字节,序号范围是[0,2^32-1]。
(4)确认号:是期望收到对方的下一个报文段的数据第一个字节的序号。若确认号 == N,则表明到序号N-1为止的所有数据都已正确收到。
(5)首部长度:最大60字节。没有任选字段,正常的长度是20字节。
(6)保留:6bit, 均为0.
(7)在TCP首部中有 6个标志比特。它们中的多个可同时被设置为 1。紧急URG、确认比特ACK、推送比特PSH、复位比特(RST)、同步比特SYN、终止比特FIN。
(8)窗口:用来控制对方发送的数据量。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。单位为字节。TCP连接的一端根据设置的缓存空间大小确定自己的接收窗口大小。然后通知发放已确定的发送窗口上限。窗口的值是经常在动态变化
(9)检验和:检验和覆盖了整个的 TCP报文段:TCP首部和TCP数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。
(10)紧急指针:紧急指针在URG=1时才有效,它指出本报文段中的紧急数据的字节数。
(11)选项:长度可变,最长可达40字节
3、TCP连接的建立
设主机B运行一个服务器进程,它先发出一个被动打开命令,告诉它的TCP要准备接收客户进程的连续请求,然后服务进程就处于听的状态。不断检测是否有客户进程发起连续请求,如有,作出响应。设客户进程运行在主机A中,他先向自己的TCP发出主动打开的命令,表明要向某个IP地址的某个端口建立运输连接,三次握手过程如下:
1)主机A的TCP向主机B的TCP发出连接请求报文段,其首部中的同步比特SYN应
置1,同时选择一个序号x,表明在后面传送数据时的第一个数据字节的序号是x。
2)主机B的TCP收到连接请求报文段后,如同意,则发送确认。在确认报文段中
应将SYN置为1,确认号应为x+1,同时也为自己选择一个序号y
3)主机A的TCP收到此报文段后,还要向B给出确认,其确认号为y+1
4)主机A的TCP通知上层应用进程,连接已经建立,当主机B的TCP收到主机A的
确认后,也通知上层应用进程,连接建立。
三次握手建立连接时,发送方再次发送确认的必要性:
主要为了防止已失效的连接请求报文段突然又传到了B,因而产生错误。假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数据,B的许多资源就这样白白浪费了。
4、TCP连接的终止
在数据传输完毕之后,通信双方都可以发出断开连接的请求。断开连接的过程为如上图所示:
1)数据传输结束后,主机A的应用进程先向其TCP发出断开连接请求,不再发送
数据。TCP通知对方要释放从A到B的连接,将发往主机B的TCP报文段首部的终止
比特FIN置为1,序号u等于已传送数据的最后一个字节的序号加1。
2)主机B的TCP收到释放连接通知后发出确认,其序号为u+1,同时通知应用进
程,这样A到B的连接就释放了,连接处于半关闭状态。主机B不再接受主机A发来
的数据;但主机B还向A发送数据,主机A若正确接收数据仍需要发送确认。
3)在主机B向主机A的数据发送结束后,其应用进程就通知TCP释放连接。主机B
发出的连接释放报文段必须将终止比特置为1,并使其序号w等于前面已经传送过
的数据的最后一个字节的序号加 1,还必须重复上次已发送过的ACK=u+1。
4)主机A对主机B的连接释放报文段发出确认,将ACK置为1,ack=w+1,
seq=u+1。这样才把从B到A的反方向连接释放掉,主机A的TCP再向其应用进程
报告,整个连接已经全部释放。
四次挥手释放连接时,等待2MSL的意义:
(1)为了保证A发送的最有一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN和ACK报文段的确认。B会超时重传这个FIN和ACK报文段,而A就能在2MSL时间内收到这个重传的ACK+FIN报文段。接着A重传一次确认。
(2)防止上面提到的已失效的连接请求报文段出现在本连接中,A在发送完最有一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。
客户端的状态可以用如下的流程来表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2
->TIME_WAIT->CLOSED
服务器的状态可以用如下的流程来表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT
->LAST_ACK->CLOSED
FIN_WAIT_2状态:
著名的半关闭的状态,这是在关闭连接时,客户端和服务器两次握手之后的状态。在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种可能是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态。