最早的 TCP 协议文档是 RFC793。
TCP 提供一种面向连接的、可靠的字节流服务。
面向连接容易理解,那么什么是字节流服务呢?
答:两个应用程序通过 TCP 连接交换 8 bit 字节构成的字节流。TCP 不在字节流中插入记录标识符。我们将这成为字节流服务(byte stream service)。另外,TCP 对字节流的内容不作任何解释。TCP 不知道传输的数据字节流是二进制数据,还是 ASCII 字符、EDCDIC 字符或者其他类型数据。对字节流的解释由 TCP 连接双方的应用层解释。这种对字节流的处理方式与 Unix 操作系统对文件的处理方式很相似。Unix 内核对一个应用读或写的内容不作任何解释,而是交给应用程序处理。对 Unix 的内核来说,它无法区分一个二进制文件与一个文本文件。
TCP 通过下列方式来提供可靠性:
- 应用数据被分割成 TCP 认为最适合发送的数据块(UDP 协议中,应用程序产生的数据报长度将保持不变)。由 TCP 传递给 IP 的信息单位称为报文段或段(segment)。
- 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。这也就是所谓的超时及重传策略。
- 当 TCP 收到发自 TCP 连接另一端的数据时,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。
- TCP 将保持它首部和数据的校验和。这是一个端到端的校验和,目的是检测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段,以便发端收取确认响应时超时并重发。
- 因为 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。如有必要,TCP 将对收到的数据进行重新排序,以正确的顺序交给应用层。
- IP 数据报也可能会发送重复,所以 TCP 的接收端必须丢弃重复的数据。
- TCP 还能提供流量控制。TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能容纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。
TCP 首部
如果不计任选字段,TCP 首部通常是 20 个字节。
-
序号用来标识从 TCP 发端向 TCP 收端发送的数据字节流,它表示在这个报文段中的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则 TCP 用序号对每个字节进行计数。序号是 32 bit 的无符号数,序号到达 2^32 -1 后又从 0 开始。
-
当建立一个新连接时,SYN 标志变 1。序号字段包含由这个主机选择的该连接的初始序号 ISN(Initial Sequence Number)。该主机要发送数据的第一个字节序号为这个 ISN 加 1,因为 SYN 标志消耗了一个序号(FIN 标志也要占用一个序号)。
-
既然每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。只有 ACK 标志为 1 时确认序号字段才有效。发送 ACK 无需任何代价,因为 32 bit 的确认序号字段和 ACK 标志一样,总是 TCP 首部的一部分。因此,我们看到一旦一个连接建立起来,这个字段总是被设置,ACK 标志也总是被设置为 1。TCP 为应用层提供全双工服务。这意味着数据能在两个方向上独立地进行传输。因此,连接的每一端必须保持每个方向上的传输数据序号。
-
TCP 可以表述为一个没有选择确认或否认的滑动窗口协议(滑动窗口协议用于数据传输)。我们说 TCP 缺少选择确认是因为 TCP 首部中的确认序号表示发方已成功收到字节,但还不包含确认序号所指的字节。当前还无法对数据流中选定的部分进行确认。例如,如果 1 ~ 1024 字节已经成功收到,下一报文段中包含序号从 2049 ~ 3072 的字节,收端并不能确认这个新的报文段。它所能做的就是发回一个确认序号为 1025 的 ACK。它也无法对一个报文段进行否认。例如,如果收到包含 1025 ~ 2048 字节的报文段,但它的校验和错,TCP 接收端所能做的就是发回一个确认序号为 1025 的 ACK。而重复的确认可以帮助发端确定分组已经丢失。
-
首部长度给出首部中 32 bit 字的数据。需要这个值是因为任选字段的长度是可变的。这个字段占 4 bit,因此 TCP 最多有 60 字节的首部。然而,没有任选字段,正常的长度是 20 字节。
-
其他首部字段
| 字段名 | 字段作用 |
| URG | 紧急指针(urgent pointer)有效 |
| ACK | 确认序号有效 |
| PSH | 接收方应该尽快将这个报文段交给应用层 |
| RST | 重建连接 |
| SYN | 同步序号用来发起一个连接 |
| FIN | 发端完成发送任务 | -
TCP 的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个 16 bit 字段,因而窗口大小最大为 65535 字节。后面还有新的窗口刻度选项,它允许这个值按比例变化以提供更大的窗口。
-
校验和覆盖了整个 TCP 报文段:TCP 首部和 TCP 数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。TCP 校验和的计算和 UDP 校验和的计算相似。
-
只有 URG 标志置为 1 时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
-
最常见的可选字段是最长报文大小,又称为 MSS(Maximum Segment Size)。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN 标志的那个段)中指明这个选项。它指明本端所能接收的最大长度的报文段。
-
从上图中可以看出:TCP 报文段的数据部分是可选的。所以我们可以从建立连接到连接终止都使用没有数据的报文段。