为什么大文件传输里丢一两个包几乎没感觉,而小请求丢一个包就卡顿?这篇用抓包比较两种丢失:窗口里有后续数据时靠重复 ACK 快速重传,只有一个包时只能等定时器,时间差 4~7 倍。
传输 2 MiB 用了 0.38 秒;tcp_info(发送方套接字):发出 135 个包,重传 3 个(48996 字节) 抓包里被重传过的段 3 个:第一次重传距首次发送的间隔小于 150 ms 的 3 个(快速重传的特征:约一个 RTT 40 ms 再加上收到 3 个重复 ACK 所需的时间),≥ 150 ms 的 0 个(超时重传的特征:RTO) 快速重传的间隔:最小 42 / 中位 42 / 最大 42 ms
接收方遇到中间有洞的段,会立刻重发“我还在等第 X 个字节”的 ACK。数到 3 个就判定丢包,不等 RTO。
段(相对序号 1045248):首次发送 +0 ms;之后到达的、确认号停在它的序号上的 ACK 共 5 个抓到记录(去掉近乎同时的重复约 1 个),时刻:[21] ms;重传发生在 +42 ms 段(相对序号 1472064):首次发送 +0 ms;之后到达的、确认号停在它的序号上的 ACK 共 16 个抓到记录(去掉近乎同时的重复约 1 个),时刻:[21] ms;重传发生在 +42 ms 段(相对序号 1521060):首次发送 +0 ms;之后到达的、确认号停在它的序号上的 ACK 共 0 个抓到记录(去掉近乎同时的重复约 0 个),时刻:[] ms;重传发生在 +42 ms 说明:接收方每收到一个序号更大、但中间有洞的段,就立刻再发一次“我还在等第 X 个字节”的 ACK(不能等延迟 ACK)。发送方数到 3 个这样的重复 ACK 就重传;为什么是 3 个:网络里偶尔乱序 1~2 个包很常见,3 个意味着很可能是真的丢了(RFC 5681)
有后续数据时重传在约一个 RTT 之后发生;没有后续数据时要等定时器,慢 4~7 倍。
60 次单包收发里,重传了 17 个包,tcp_info 显示重传 24 个;首次重传的间隔最小 181 / 中位 189 / 最大 275 ms——都在 RTO 量级(≥ 200 ms),远大于一个 RTT(40 ms),因为没有后续数据产生重复 ACK 所以快速重传只对“窗口里有后续数据”的丢失有效;请求 / 应答式的小消息丢了只能靠 RTO。
请求 / 应答式的小消息对丢包最敏感,因为没有后续数据产生重复 ACK;所以小消息的延迟尾巴主要来自定时器。