如何在继续之前明确等待TCP ACK?

9
有没有一种方法可以让send()等待,直到已发送的所有数据都已被ACK-ED(或者如果已达到ACK的超时,则返回-1),或者在进行其他操作之前等待ACK的某些其他机制?
我正在使用标准的Unix Berkeley套接字API。
我知道我可以实现应用程序层ACK,但当TCP的ACK完全满足目的时,我宁愿不这样做。

4
你错了,TCP ACK并不起到那个目的。它告诉发送方内核接收方内核已经收到了这些字节,而不是目标应用程序(该程序甚至可能根本没有从套接字读取任何内容)。 - Nikolai Fetissov
在你开始随意使用“TCP ACK”这样的术语之前,你可能需要费心去了解ACK是如何实现以及它的含义。 - Pete Wilson
4个回答

6

据我所知,目前没有任何方法。

并且,这样做也不可靠,ACK仅意味着内核已接收到数据,在此期间,客户端或其计算机可能已经崩溃。虽然您会认为客户端已经接收了数据,但实际上它从未处理过该数据。


2
这并不准确。ACK 不是来自您本地的内核,而是来自远程端的内核代码,正如 Nikolai 上面提到的那样。因此,它保证数据包已经到达远程终点,但并不一定意味着远程用户应用程序已经读取了它。 - TJD
2
@TJD:我在谈论远程内核,我以为这是显而易见的。 - Karoly Horvath
1
@yi_H,你说“客户端或其机器可能已经崩溃”,这让人感到不太清楚。我没看懂你的意思是内核确认后客户端机器可能已经崩溃,但客户端应用程序尚未读取数据。 - TJD
TCP的正确答案和一个被误解的部分是,大多数应用程序需要对每个请求都有一个应用层响应。ACK结构体并不能帮助这一点,因为它只是远程内核的接收。你应该更新你的响应,明确地指出它是远程内核,就像你打算的那样。 - Brian Bulkowski

5

很遗憾,标准API没有任何适当的方法来实现此功能。虽然可能有一种方法可以查询当前TCP发送窗口大小/使用情况,但不幸的是它可能无法通过标准方式查询。

当然,有一些巧妙的方法可以达到你想要的效果。例如,在Windows上可以创建网络过滤驱动程序来监视数据包级别的流量。


2

我似乎已经找到了一个解决方案。至少在Linux上,如果你将SO_SNDBUF设置为0,它似乎会在允许下一次传输之前等待每个事务。虽然它会立即返回,但是在前一个发送完成之前,它不会继续允许另一个发送成功。我还没有尝试使用select(...)来确定数据是否已发送。

这在我的Linux 3.8内核上可以工作,并且我有信心它也可以在其他地方工作。


我在6.0.0内核上尝试了这个,但没有观察到相同的行为(仅供运行更近期内核的人们参考)。 - 9072997

1

你可以为send()编写一个包装器。我在另一个线程中回答了类似的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接