我了解 acks 和 windowing 的工作原理。但我不明白的是,为什么我在数据包捕获中看到以下行为
Client Server
data1----->
data2----->
<--------ack
当服务器确认数据 2 时,客户端如何知道数据 1 没有丢失?因为我没有看到该数据的任何 ACK。
答案1
正如您所说的“段”,我假设这是 TCP。
因此,ACK 并不确认数据包,它承认数据。正如 @infixed 所说,“如果在标志字段中设置了 ACK 标志,则确认号表示到该点的数据已经过验证” - 如果第一个客户端 TCP 段发送了具有(相对)序列号 0 到 24 的数据 - 即 25 个字节的数据,从(相对)序列号 0 开始 - 并且第二个客户端 TCP 段发送了具有(相对)序列号 25-49 的数据 - 即 25 个字节的数据,从(相对)序列号 25 开始,这是第一个段后第一个字节的(相对)序列号 - 然后服务器可以发送一个数据包说“我已经收到了直到(相对)序列号 49 的所有数据”,它确认来自两个都这些数据包。
此外,正如 @infixed 所说,TCP 有一个选项允许接收方确认给定范围内的部分数据,但不是全部数据。如果第一个 TCP 段没有到达服务器,但第二个段到达了,服务器可以使用“选择性确认”来表示“我已收到(相对)序列号 25 和 49 之间的所有数据”,这样客户端就知道它必须重新传输第一个段,但不是第二部分。
答案2
简而言之,一个 ACK 确认了您正在查看的两个数据包。
每个数据不必都有一个特殊的 ACK 数据包。
虽然 TCP 有一项称为选择性确认的增强功能,但 TCP 并未严格要求它。(不过,如今大多数堆栈都有它)
常规 ACK 是 TCP 报头的一部分。如果在标志字段中设置了 ACK 标志,则确认号表示到该点为止的数据已得到验证。此标志通常设置在除第一个数据包之外的每个数据包上。另一个字段表示它有空间来接受一定数量的更多数据。
维基百科可以为你提供有关 TCP 段头的更多详细信息,这可能会让你更清楚
或者 RFC 793 中的经典 ASCII 艺术
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+