(三)TCP 协议
1. TCP 协议
面向连接的传输层协议;
点对点(1v1)的传输协议,只能有一个起点和一个终点;
提供可靠的交付服务;
全双工通信;
面向字节流:即报文是被划分到字节为单位进行连续传输;

序号机制:通过将每个字节编号,可以进行差错检查,确保数据可靠传输;
一个 TCP 报文段包含的字节数:由 TCP 根据接收方给出的窗口值和当前网络拥塞程度来决定;
划分 + 积累:可将长数据块划分为多个块发送;也可等待缓存有足够数量字节后再发送;
2. TCP 报文段(⭐)

2.1. 字段解析
源端口和目的端口:都是 2 字节,同 UDP 首部;
序号(seq):4 字节,数据部分第一个字节的序号;
确认号(ack):用于确认收到发送方发来的字节流,为收到的字节最大序号 +1(链路层累计确认机制);
数据偏移:数据部分在整个报文段的偏移,即首部长度,单位为 4 字节;
单字节标志位
ACK,SYN:用于建立连接;FIN:用于释放连接;
ACK:为 1 表示确认号有效,TCP 连接建立后,除开始的 SYN 报文,所有报文必有
ACK=1;SYN:用于建立 TCP 连接,同步双方的初始序列号(ISN);
FIN:用于释放 TCP 连接,四次挥手;
URG(urgent):表示紧急,数据需要马上发送;
PSH(push):表示快速提交,指示 TCP 不要继续等待更多数据,而是马上将当前数据提交给应用;
RST(reset):重置连接;
窗口:接收方表示自己当前能够接收的最大数据量,用于发送方划分报文;
- 若窗口大小过大无法表示,则可用选项部分来扩展表示;
检验和:计算方法同 UDP,也需要伪首部;
紧急指针:了解;
选项字段(长度可变)
窗口扩大 S:3 字节,表示将原有窗口值向左移位 S 位,得到新的窗口值;
时间戳:10 字节,主要是时间戳值(4 字节)和时间戳回送回答(4 字节);
2.2. 最大报文段长度 MSS
表示能接收报文的数据字段最大长度,单位字节;
- MSS = 最大 TCP 报文段总长度 - 首部长度;
MSS 和接收窗口值 win 无关,二者的区别分析:
窗口值 win
用于限制一段时间内发送方发送的总数据量;
可协商,且动态变化的。随数据的发送和接收方拥塞情况的变化而改变;
目的:防止发送方持续发送大量数据,造成接收方过载;
MSS
用于限制每个 TCP 报文段的长度;
一般是在建立连接时固定,连接释放前不变;
目的:选择合适的 MSS,让 ip 层不分片的同时传输一次尽可能多的数据,提高传输效率;
MSS 对传输效率的影响分析
MSS 过小,如 MSS = 1:则每个 ip 数据报含 40 字节头部(ip + TCP)和 1 字节数据,效率很低(1/41);
MSS 过大,则 ip 层传输时会进行大量分片,接收方需要重组,且一片出错将导致整个报文重传,因此可靠性和传输效率均会降低;
ip 层经过不同路径传输时,最佳 MSS 也是不同的,因此全局最佳 MSS 很难确定;
3. TCP 连接管理(⭐)
3.1. TCP 连接三个阶段
1)连接建立;
2)数据传输;
3)连接释放;
3.2. TCP 连接的要点
要使得双方都能够确认对方的存在和可达性;
允许双方协商一些通信参数(MSS,win,服务质量等);
分配传输实体资源(分配缓存大小,建立连接表及其表项);
3.3. TCP 连接的建立
客户—服务器(C/S)模式:主动发起建立连接的应用为客户端(client)被动等待连接建立的为服务器(server);
三步握手(三报文握手)过程(⭐)

为客户端初始序号, 为服务器初始序号。 和 都是随机生成,以免历史报文干扰; - 初始序列号仅为标识用,不表示实际数据字段的大小(实际上数据字段并无数据);
后续报文的 ack 值和 seq 值不归零,在
和 的基础上增长; MSS 协商:在三次握手中协商 MSS 值,最终取较小值作为本次连接 MSS;
3.4. TCP 连接的释放:四步(四报文)握手

假设客户端主动关闭。若服务器主动关闭,则情况对称;
客户端 FIN-WAIT-1 状态:已发送 FIN 报文,正在等待 ACK 报文;
客户端 FIN-WAIT-2,服务器 CLOSE-WAIT 状态,:服务器单方面向客户端发送剩余数据。服务器发送 FIN 报文时,表示数据发送完毕;
服务器 LAST-ACK 状态:发送了 FIN 报文,等待 ACK 报文;
客户端 TIME-WAIT 状态:客户端收到 FIN 报文,并回送了 ACK 报文,客户端需进入 TIME-WAIT 状态并等待 2MSL 的时间,才能关闭连接;
作用 1:确保服务器正确收到 ACK 报文,若 ACK 报文丢失,服务器会重传 FIN 报文,此时客户端就可以再次回复 ACK;
作用 2:确保其他连接(通常是上次连接)的报文消失,防止干扰;
场景:无 TIME-WAIT
连接 1:seq=3 的报文被重传,还未得到 ACK 回复,连接 1 被异常关闭;
连接 2:在连接 1 关闭后的很短时间内建立,且通信双方完全相同(连接重用),服务器接收了 seq=1 和 seq=2 报文;
分析:连接 1 的 seq=3 的报文可能在连接 2 的 seq=1 和 seq=2 的报文后到达服务器,使得服务器误认为此条报文是连接 2 的,造成错误;
4. TCP 可靠传输
4.1. 可靠传输特点
TCP 连接的每一端都必须设有两个窗口:1 个发送窗口和 1 个接收窗口;
TCP 靠传输机制用字节的序号进行控制;
TCP 所有的确认都是基于序号而不是基于报文段;
TCP 两端的四个窗口经常处于动态变化之中;
TCP 连接的往返时间 RTT 不是固定不变,需要使用特定的算法估算较为合理的重传时间;
4.2. 发送和接收 - 滑动窗口
和链路层传输过程相似;
Step 1. 构造:发送方 A 根据 B 给出的窗口值,构造出发送窗口;

Step 2. A 发送了 11 字节的数据 31~41;

注意
, 和 三个部分的含义; TCP 允许字节不按序收到(图中的 32 和 33);
Step 3. A 收到 ACK=34 报文,发送窗口向前滑动;

- 对于已发送但未确认的部分(34~41),TCP 也具有超时重传机制;
Step 4. A 的发送窗口满,停止发送

要点
A 的发送窗口不总是和和 B 的接收窗口一样大(win 改变时需要报文通知,时间会有一定的滞后);
TCP 标准没有规定对不按序到达的数据应如何处理;
- 通常是先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程;
TCP 要求接收方必须有累积确认的功能,以减小传输开销;
4.3. 时间参量 RTTs,RTO
RTTs:加权平均往返时间
计算:每测量到一个新的 RTT,令
; , 越小表示 RTTs 更新越慢,反之越快; 一般(推荐)
,为 RFC 2988 推荐值;
RTO:超时重传时间
计算 RTO(RFC 2988):
- RTTD:为 RTT 偏差的加权平均值;
计算 RTTD(RFC 2988)
第一次测量:
; 更新:
; 为小于 1 的系数,推荐值为 ;
Karn 算法:报文段重传时,忽略其
样本。可使得 RTTs 和 RTTD 更加准确; 修正 Karn 算法
重传发生时,手动增大 RTO:
, 一般为 2; 不再发生重传时,按照 RFC 公式计算 RTO;
5. TCP 流量和拥塞控制
5.1. 概念
流量控制(flow control)
局部性的过程:在给定的发送端和接收端之间的点对点通信量的控制;
限制发送速率,使得接收方来得及接收,且网络不发生拥塞;
拥塞控制(congestion control)
前提:网络能够承受现有的负荷;
全局性的过程:涉及到所有主机、路由器,以及与降低网络传输性能有关的所有因素;
5.2. TCP 流量控制

连接建立时,接收方 B 向发送方 A 说明:接收窗口值 rwnd = 400 字节;
传输过程中,rwnd 可动态改变,如 B 的第一个回送 ACK 报文将 rwnd 更新为 300;
注意:A 允许传输的数据要结合 B 回送 ACK 报文中,ack 和 rwnd 的字段一起确定;
如:B 第一个 ACK 报文,A 允许发送第 201 至第 500 共 300 字节,不是随意发送 300 字节;
在 rwnd=0 时,A 不允许发送新的数据,但可重传丢失的旧数据;
5.3. TCP 拥塞控制
拥塞窗口
发送方持有拥塞窗口(congestion window,cwnd),用于限制发送窗口大小;
- 一开始发送窗口 = 拥塞窗口,若接收方接收窗口较小,则发送窗口可小于拥塞窗口;
拥塞窗口大小随网络拥塞程度动态变化;
慢开始算法

发送方最开始时,设置
; 发送方每收到一个新报文段的确认,更新
,逐步增大 cwnd; - 重传的报文不算在内;
由于发送方一次性将 cwnd 个报文连续发送,也一般是连续收到确认,因此 cwnd 是指数增长;
如图,每经过一个传输轮次,发送方 cwnd 变为 2 倍;
传输轮次:指发送方将拥塞窗口内报文段连续发送,并收到最后一个字节的确认的总时间,一般为 RTT;
慢开始门限 ssthresh:避免慢开始的指数增长使得 cwnd 过大;
- 当
时,使用慢开始,否则,使用拥塞避免算法;
- 当
拥塞避免算法

加法增大:每经过一个往返时间 RTT(传输轮次),使
,cwnd 线性增长; 网络出现拥塞时
判断:没有按时收到确认 ACK;
乘法减小:减小 ssthresh 为拥塞时发送窗口的一半(不小于 2);
重置窗口:将 cwnd 重置为 1,重新执行慢开始;
图中 cwnd 的单位为 MSS(即一个报文段的长度);
快重传(3-ACK)

接收方:每收到一个失序的报文后,立即回送重复 ACK 确认;
发送方:若连续受到 3 个相同的 ACK,则立即重传缺失的报文;
- 3-ACK 机制独立运行,不会重置超时重传计时器;
快恢复:一般发生在快重传之后
将 cwnd 减半而不重置为 1,更新 ssthresh 为新 cwnd;
不启用慢启动算法,而是继续使用拥塞避免算法,线性增长;
TCP Reno 版本在快重传发生之后使用快恢复(不常考);
TCP Tahoe 版本在快重传发生之后重置并慢启动(常考);