传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

file
上图描绘了TCP与TCP/IP协议族中其他协议的关系。TCP位于应用层和网络层之间,它提供介于应用程序和网络功能之间的服务。

与UDP一样, TCP也使用端口号提供进程到进程的通信。下图给出了TCP使用的一些熟知的端口号:
file

流交付服务

与UDP不同,TCP是一种面向流的协议。

在UDP中,进程把已预先定义好边界的报文发送给UDP以便进行交付。
UDP对每个报文都添加上自己的首部,然后再把它们传递给IP来传输。从进程发来的报文称为用户数据报,并最终成为IP数据报。不论是UDP还是IP,都不认为这些数据报之间存在任何的关联。

然而,TCP则允许发送进程以字节流的形式来传递数据,并且也允许接收进程把数据作为字节流来接收。
在TCP中,可以把两个进程假象为一个“管道“,而这个管道经过因特网传输着两个进程之间的数据。
file

发送缓存和接收缓存

因为发送进程和接收进程可能以不同的速度写入数据和读取数据,因此TCP需要用缓存来存储数据。此处有两个缓存,即发送缓存和接收缓存,每个方向各一个。
缓存的一种实现方法是使用由1字节位置组成的环形阵列file
图中描绘的是单向的数据移动过程。在发送方,该缓存有三种类型的槽。
白色区域包含的是空槽,允许发送进程(生产者)填入数据。
深灰色区域保存的是已经发送出去但还没得到确认的字节。发送TCP在缓存中保存这些字节,直至收到相应的确认。
灰色区域表示发送TCP将要发送的字节。

接收方的缓存操作较为简单。环形缓存被划分为两个区域(白色和灰色)。
白色区域包含的空槽将被从网络中接收到的字节填入。
灰色区域包含的是已经接收到的字节,这些字节将被接收进程读取。当一个字节被接收进程读取后,相应的槽就可以被回收,并加入到空槽池中。

报文段

虽然可以用缓存来处理生产进程和消耗进程在速度上的差异。但我们在发送数据之前还需要一个步骤。
IP层作为TCP的服务提供者,它必须以分组为单位发送数据,而不是按字节流来发送。
在运输层,TCP把若干字节组成一个分组,称为报文段。
TCP给每个报文段添加一个首部(用于控制),然后再把这个报文段交付给IP层传输
这些报文段被封装成IP数据段后发送出去
下图描绘了如何用缓存中的字节构成报文段。
file

这些报文段并不一定长度相同。在图中,为简单起见,我们描绘了一个报文段有3字节。而另一个报文段有5字节。实际上,报文段可以是几百字节长,甚至几千字节长。

全双工通信

TCP提供全双工服务,即数据可在同一时间双向流动。TCP的两个端点分别有自己的发送缓存和接收缓存,报文段可以在两个方向运动。

复用和分用

与UDP一样,TCP在发送端执行复用并在接收端执行分用。
但是,因为TCP是一个面向连接的协议,所以每一对进程都需要建立一条连接。

TCP是一个可靠的传输协议。它使用确认机制来检查数据是否安全完好地到达。

TCP的特点

编号系统、流量控制、差错控制、堵塞控制

编号系统

虽然TCP软件需要掌握正在传送的或已接收到的每一个报文段,但在报文段首部中并没有存放报文段编号值的字段。
实际上,在这个首部中有两个叫做序号和确认号的字段。
而这两个字段所指的都是字节的编号而不是报文段的编号。

字节号

TCP把在一个连接中要发送的所有数据字节(八位组)都编上号。两个方向的编号是相互独立的。
当TCP接收来自进程的数据字节时,就把它们存储在发送缓存中,并为它们进行编号。编号不一定要从0开始。
TCP选择0~(2的32次方-1)之间的一个随机数作为第一个字节的编号。
例如,若这个数恰巧是1057,而要发送的数据总共有6000字节,那么这些字节的编号就是从1057~7056

每条连接上传送的数据字节都被TCP编了号。编号从一个随机产生的数开始。

序号

当字节都被编上号以后,TCP就给每一个要发送的报文段指派一个序号。每个报文段的序号就是这个报文段中第一个数据字节的序号。

假设一条TCP连接要传送一个5000字节的文件。第一个字节的编号是10001.如果该数据用5个报文段来发送,且每个报文段携带1000字节的数据,那么每个报文段的序号分别是什么?

file

报文段的序号字段值定义的是这个报文段包含的第一个数据字节所分配的编号。

当一个报文段同时携带了数据和控制信息(捎带)时,它使用一个序号。但如果报文段不携带用户数据,从逻辑上讲,它就不定义序号。
序号字段总是存在的,但它的值是无意义的。不过某些仅携带控制信息的报文段还是需要有一个序号,以便于接收方的确认。
这些报文用于连接建立、连接终止和连接异常终止
这每一个报文段都要消耗一个序号,就好像它携带了一个字节的数据,但实际上是没有数据的

确认号

TCP的通信是全双工的。当一条连接建立后,双方能同时发送和接收数据。通常双方从不同的起始号开始对字节编号。每一个方向上的序号表示的是该方向对报文段所携带的第一个数据字节的编号
双方还使用了确认号对各自收到的字节表示确认,不过这个确认号定义是它期望接收的下一个字节的编号。
另外,确认号是累积的,也就是说,它把收到的最后一个(完全完好)字节的编号加上1所得到的值 宣布为确认号
【注意,这里如果某一方使用5643作为确认号,那就表示它已经收到了从开始一直到编号为5642的所有字节。换句话说,并不是说这一方已经收到了5642个字节,因为第一个字节的编号不一定是从0开始】

报文段中确认字段的值定义了某一方期望接收的下一个字节的编号。
确认号是累积的。

流量控制

和UDP不同,TCP提供了流量控制。
发送TCP要对能够接受多少从发送进程传来的数据进行控制,接收TCP则要对发送TCP能够发送多少数据进行控制。
这样做是为了防止接收方因数据过多而来不及处理

差错控制

为了提供可靠的服务,TCP需要实现差错控制机制。虽然差错控制把报文段看作是差错检测的数据单元(报文段丢失或受损伤),但TCP的差错控制是面向字节的。

堵塞控制

和UDP不同,TCP要考虑到网络的堵塞状况。
发送方允许发送的数据量不仅要受接收方的控制(流量控制),而且还要由网络的堵塞状况来决定。

最后修改:2022 年 03 月 08 日
如果觉得我的文章对你有用,请随意赞赏