🔌 第二章 用电信号传输TCP/IP数据
📄 一句话概括

TCP 头里 ACK 号与窗口字段搭同一辆车——确认与报余量合并成一次往返,省一半的包。

📝 本节和前面几节的关系

2.3.3 的 ACK 与 2.3.5 的窗口是两件事;本篇讲它们的合体。

一、一包两用

每次回 ACK 时顺手带上最新窗口值—— 对账(收到哪了)与通告(还能收多少)一次说清。

二、为什么值得合并

分开发要双倍报文;合起来只多 2 字节(窗口字段)。 小设计大收益——协议设计的品味所在。

三、动手 Demo:ACK 和窗口搭一辆车

一个报文里的两笔账:

for f, c, u in [('ACK 号','b+2920','对账:收到哪了'),
               ('窗口','5840','余量:还能收多少')]:
    print('%-7s %-8s %s' % (f, c, u))

实跑输出:

--------------------------------------------------------------------
ACK 和窗口搭一辆车
--------------------------------------------------------------------
  回 ACK 顺便报窗口,一条包两件事:

  报文字段     内容       作用
  ---------------------------------------------
  ACK 号       b+2920     对账:收到哪了
  窗口         5840       对账之外:还能收多少
  ---------------------------------------------

  所以【确认】和【报余量】合并成一次往返——
  省一半的包,这是 TCP 效率的巧劲之一。

对照 1.4.4【协议栈不问内容】:协议栈对账用头, HTTP 分界用体——同一趟车两层分工。

30 秒实验

  1. Wireshark 里同一包同时看 ack 与 win 两个字段。
  2. 算算若 ACK 与窗口分开报,多花多少包。
  3. 想想还有哪些协议用【搭车】设计(如 HTTP 头与体)。

常见误区

  1. 以为 ACK 包只报确认——它还带窗口。
  2. 以为合并是优化可选——TCP 头设计即如此。
自测三问(点开对答案) 1. ACK 报文里搭车的是什么? —— 窗口字段。 2. 合并省了什么? —— 一半的往返报文。 3. 窗口字段收缩到 0 会怎样? —— 发送方暂停,等新通告。

相关笔记