遇到一个供应商的问题,该供应商声称问题的原因是 tcp 数据中的无效“ack”值。我使用的是 java,所以我没有编写这一层。我使用 snoop 捕获线路上的流量,并使用 wireshark 显示数据。这是正在发生的事情。收到多数据包(5)消息后,我看到了多数据包(3)响应。响应中的第一个数据包的“ack”值与其他两个数据包中的“ack”值不同。供应商声称这些数据是可疑的。我在下面提供了示例数据。我不是 tcp 专家,所以我不知道这是否是个问题。我试图找到一些关于有效 ack 值的东西,在我看来,这个值应该是 80018,但这并不意味着 78345 是错误的。我在网上找到了这个,它似乎适用,但我不确定:“任何数据段的 ack 值只要不在下一个要发送的段之前确认数据,就被视为有效”。谢谢你的帮助。我的理解是供应商已经编写了自己的 tcp 层。
源序列确认长度时间 我 10734 75465 190 年月日 09:18:21.785757 供应商 75465 10924 0 yyyymmdd 09:18:21.789319 供应商 75465 10924 1440 yyyymmdd 09:18:34.196661 供应商 76905 10924 1440 yyyymmdd 09:18:34.196762 供应商 78345 10924 1440 yyyymmdd 09:18:34.196901 供应商 79785 10924 233 yyyymmdd 09:18:34.196915 我 10924 78345 0 年月日 09:18:34.196968 我 10924 80018 0 年月日 09:18:34.197102 我 10924 80018 197 年月日 09:18:34.579479
答案1
http://en.wikipedia.org/wiki/Transmission_Control_Protocol说
确认号(32 位)——如果设置了 ACK 标志,则此字段的值是接收方期望的下一个序列号。这确认已收到所有先前的字节(如果有)。每一端发送的第一个 ACK 确认另一端的初始序列号本身,但不确认数据。
这表明第一个回复数据包确认收到了来自小贩(序号 76905 + 长度 1440 = 78345)
第二个回复数据包确认收到来自小贩(序号 79785 + 长度 233 = 80018)
第三个回复数据包表示没有收到来自小贩(相同的确认)并包含 197 字节的有效载荷。
对我来说这看起来不错。
如果你的数据是整个对话,那么初始确认将是错误的,因为它应该确认来自小贩确认为 75465(序号 75465 + 1 = 75466)。
下面是我用 wireshark 捕获的序列,首先我们看到三次握手,然后是 HTTP get 请求的传输,接着是 HTTP 响应
源标志序列确认长度 客户端 SYN 0 - 0 服务器 SYN,ACK 0 1 0 客户端 ACK 1 1 0 客户端 - 1 1 429 获取... 服务器 ACK 1 430 0 服务器 - 1 430 1456 HTML 响应 服务器 - 1457 430 1456 客户端确认 430 2913 0 ...
序列号和确认号是相对的(相对于每一端随机选择的起始号)
使用单个连接来处理一系列请求是一种常见的优化方法。它被添加到 HTTP 1.1 版本中,被称为持久连接. 建立和拆除 TCP 连接是有成本的。
答案2
简而言之,ACK 字段用于指示接收方期望从发送方收到的下一个序列号。即,最后收到的段的序列号 + 该段的长度。(还有一些与处理丢失/重传相关的其他用途,但我们现在先不讨论这些)。
TCP 的设计使得可以在单个响应中确认多个段。这样可以更有效地利用高延迟链路。请参阅RFC1122和RFC2581,特别是有关延迟确认的部分。
就您的具体问题而言:TCP 堆栈始终会存在一定程度的交错;也就是说,即使最后一个数据包(序列号 79785)已放置在接收缓冲区中,在必须将 ACK 发送回连接的另一端之前,它也可能未在允许的时间内得到处理。您提供的标头在我看来似乎描述了一次完全正常的 TCP 对话。您的供应商的解释充其量也令人生疑。