简介

TCP是TCP/IP体系中非常复杂的一个协议。下面介绍TCP最主要的特点。

  • TCP是面向连接的传输层协议。这就是说,应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。
  • 每一条TCP连接只能有两个端点(endpoint),每一条TCP连接只能是点对点的(一对一)。
  • TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达。
  • TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发送出去。在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。
  • 面向字节流。TCP中的“流”(stream)指的是流入到进程或从进程流出的字节序列。“面向字节流”的含义是:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。TCP并不知道所传送的字节流的含义。TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系(例如,发送方应用程序交给发送方的TCP共10个数据块,但接收方的TCP可能只用了4个数据块就把收到的字节流交付上层的应用程序)。但接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。当然,接收方的应用程序必须有能力识别收到的字节流,把它还原成有意义的应用层数据。

TCP连接的端点叫做套接字(socket)或插口。根据RFC 793的定义:端口号拼接到(contatenated with) IP地址即构成了套接字。

套接字(socket) = IP:端口

可靠传输

TCP发送的报文段是交给IP层传送的。但IP层只能提供尽最大努力服务,也就是说,TCP下面的网络所提供的是不可靠的传输。因此,TCP必须采用适当的措施才能使得两个传输层之间的通信变得可靠。

理想的传输条件有以下两个特点:

  • 传输信道不产生差错。
  • 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。

停止等待协议

“停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。

A只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组。这就叫做超时重传。要实现超时重传,就要在每发送完一个分组设置一个超时计时器。如果在超时计时器到期之前收到了对方的确认,就撤销已设置的超时计时器。

这里应注意以下三点。

  • A在发送完一个分组后,必须暂时保留已发送的分组的副本(为发生超时重传时使用)。只有在收到相应的确认后才能清除暂时保留的分组副本。
  • 分组和确认分组都必须进行编号。这样才能明确是哪一个发送出去的分组收到了确认,而哪一个分组还没有收到确认。
  • 超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些。重传时间应设定为比平均往返时间更长一些。显然,如果重传时间设定得很长,那么通信的效率就会很低。但如果重传时间设定得太短,以致产生不必要的重传,浪费了网络资源。然而,在传输层重传时间的准确设定是非常复杂的,这是因为已发送出的分组到底会经过哪些网络,以及这些网络将会产生多大的时延(这取决于这些网络当时的拥塞情况),这些都是不确定因素。

使用上述的确认和重传机制,就可以在不可靠的传输网络上实现可靠的通信。像上述的这种可靠传输协议常称为自动重传请求ARQ(Automatic Repeat reQuest)。

停止等待协议的优点是简单,但缺点是信道利用率太低。

连续ARQ协议

为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是采用流水线传输。流水线传输就是发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。这样可使信道上一直有数据不间断地在传送。显然,这种传输方式可以获得很高的信道利用率。

滑动窗口协议比较复杂,是TCP协议的精髓所在。

Produced by OmniGraffle 7.18.5\n2021-10-17 09:16:48 +0000Canvas 1Layer 11234567812345678t收到一个确认后,发送窗口向前移动

协议格式

Produced by OmniGraffle 7.18.5\n2021-10-17 09:58:08 +0000Canvas 1Layer 116318240源端口目标端口序号确认号数据偏移保留FINSYNRSTPSHACKURG窗口校验和紧急指针选项(长度可变)填充
  • 源端口和目的端口

    各占2个字节,分别写入源端口号和目的端口号。

  • 序号

    占4字节。序号范围是[0, 232 - 1],共232(即4 294967 296)个序号。序号增加到232 - 1后,下一个序号就又回到0。也就是说,序号使用mod 232运算。

  • 确认号

    占4字节,是期望收到对方下一个报文段的第一个数据字节的序号。

  • 数据偏移

    占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。

  • 保留

    占6位,保留为今后使用,但目前应置为0

  • 紧急URG

    当URG = 1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送。

    例如,已经发送了很长的一个程序要在远地的主机上运行。但后来发现了一些问题,需要取消该程序的运行。因此用户从键盘发出中断命令(Control + C)。

  • 确认ACK (ACKnowlegment)

    仅当ACK = 1时确认号字段才有效。当ACK = 0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。

  • 推送 PSH (PuSH)

    当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接收方TCP收到PSH = 1的报文段,就尽快地(即“推送”向前)交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。

  • 复位RST (ReSeT)

    当RST = 1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。

  • 同步SYN (SYNchronization)

    在连接建立时用来同步序号。当SYN = 1而ACK = 0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN = 1和ACK =1。因此,SYN置为1就表示这是一个连接请求或连接接受报文。

  • 终止FIN (FINis,意思是“完”、“终”)

    用来释放一个连接。当FIN = 1时,表明此报文段的发送方的数据已发送完毕,并要求释放传输连接。

  • 窗口

    占2字节。窗口值是[0, 216 - 1]之间的整数。窗口指的是发送本报文段的一方的接收窗口(而不是自己的发送窗口)。窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值作为接收方让发送方设置其发送窗口的依据。

  • 检验和

    占2字节。检验和字段检验的范围包括首部和数据这两部分。

    和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。

  • 紧急指针

    占2字节。紧急指针仅在URG = 1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)

  • 选项

    长度可变,最长可达40字节。当没有使用“选项”时,TCP的首部长度是20字节。

TCP 连接管理

TCP是面向连接的协议。传输连接是用来传送TCP报文的。TCP传输连接的建立和释放是每一次面向连接的通信中必不可少的过程。因此,传输连接就有三个阶段,即:连接建立、数据传送和连接释放

在TCP连接建立过程中要解决以下三个问题:

  1. 要使每一方能够确知对方的存在。
  2. 要允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等)。
  3. 能够对传输实体资源(如缓存大小、连接表中的项目等)进行分配。

建立连接

三次握手

Produced by OmniGraffle 7.18.5\n2021-10-17 13:38:04 +0000Canvas 1Layer 1RectangleBRectangleACLOSEDSYN-SENTESTABLISHEDCLOSEDSYN-RCVDESTABLISHEDLISTENSYN=1SYN=1,ACK=1传输数据ACK=1

释放连接

Produced by OmniGraffle 7.18.5\n2021-10-25 00:10:13 +0000Canvas 1Layer 1RectangleBRectangleACLOSEDFIN-WAIT-1ESTABLISHEDCLOSEDCLOSE-WAITESTABLISHEDFIN=1ACK=1ACK=1FIN-WAIT-2TIME-WAITFIN=1,ACK=1等待2MSL