【问题标题】:TCP Sockets in C: Does the recv() function trigger sending the ACK?C 中的 TCP 套接字:recv() 函数是否触发发送 ACK?
【发布时间】:2022-12-10 16:19:40
【问题描述】:

我在 C 中使用 TCP 套接字,但还没有真正理解“多远”的数据传输。

我的主要问题是,在我的情况下,服务器有时会向客户端发送一条消息,并希望很快得到答复。如果客户端没有及时应答,服务器将关闭连接。 在阅读 C 中 recv() 函数的联机帮助页时,我发现了 MSG_PEEK 标志,它让我可以在不实际读取数据的情况下查看/窥视流。

但是服务器是否关心我是否从流中读取?

假设服务器将一系列消息“推送”到流中,客户端应该接收它们。 只要客户端不调用 recv() 那些消息就会保留在 Stream 中,对吗? 我知道在接收数据时正在发送 ACK 消息,但是当我调用 recv() 函数时是否发送了 ACK,或者当消息成功到达目的地时是否已经发送了 ACK 并且如果客户端选择(强调可以)可以接收它调用 recv()?

我的希望是欺骗服务器认为消息还没有完全发送,因为客户端还没有调用 recv()。因此,客户端已经可以通过使用 MSG_PEEK 标志评估消息并确保它始终及时答复。 当然我知道我的服务器超时取决于实现。我的问题基本上是,如果 PEEKING 让服务器认为消息还没有到达它的目的地,或者服务器是否甚至不关心以及何时在使用 recv() 时发送 ACK。

我阅读了有关 recv() 的联机帮助页和 TCP 上的 wiki,但无法真正弄清楚 recv() 如何参与该过程。我在 SO 上发现了一些类似的问题,但没有回答我的问题。

【问题讨论】:

  • 不,您阅读时不会发送 ACK。
  • 你可能想把它想象成好像有流:您的机器(您机器的操作系统)和服务器之间的 TCP 流,以及您机器的操作系统和您的程序之间的流。当收到 TCP 数据包时,您的操作系统会确认它们并将它们组装到缓冲区中,等待您的程序读取它们。当您的程序读取时,它会耗尽该缓冲区。
  • 如果您遇到代码无法及时响应服务器输入的问题,我相信您会想要重新安排程序的体系结构,而不是尝试使用 ACK 来耍花招。特别是,您希望 (a) 您的程序大部分时间都在阻塞 readrecv 调用等待输入(这意味着它保证立即响应),或者 (b) 您的程序是事件-driven,这样一来它知道输入可用时,它就会去读取它。
  • 如果您花费大量时间进行处理,这就是导致您错过来自服务器的消息的原因,您可能希望切换到多线程架构,这样您就可以让一个线程进行处理,一个线程与服务器通信。
  • 现在,我所说的一切都假设您的 C 程序运行在成熟的操作系统下,具有传统的网络堆栈。如果你在做嵌入式编程,事情可能会完全不同。 (特别是,在嵌入式系统中,很可能不是是你这边的中间缓冲区,其中接收到的 TCP 流的某些部分正在组装,等待你的程序读取它。)

标签: c sockets tcp ack


【解决方案1】:

长话短说

recv() 函数是否触发发送 ACK?

不,不是在任何常规操作系统上。可能在网络堆栈效率低下的嵌入式平台上。但无论如何,这几乎肯定是错误的问题。


你关于处理 ACK 传递细节的问题是一大堆蠕虫。它是一个实现细节,这意味着它是高度特定于平台的。例如,您可以修改某些 TCP 堆栈上的延迟 ACK 计时器,但如果它存在的话,那可能是一个全局内核参数。

但是,这与您的实际问题无关。服务器几乎没有机会查看何时收到数据包,因为它需要它自己的 TCP 堆栈才能猜测到这一点,而且它仍然不可靠(TCP 重传可以继续后退并重试分钟).服务器正在查看发送数据的时间,您不能影响它。

您可以获得的最接近的情况是服务器使用阻塞写入并且是单线程的并且您用未确认的数据填充接收窗口。但这可能会延迟服务器注意到您迟到而不是真正欺骗它。

只需让您的处理速度足够快以避免超时,而不是试图与 TCP 撒谎。

【讨论】:

    猜你喜欢
    • 2011-04-04
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 2012-03-06
    • 2014-02-21
    • 2018-09-13
    • 1970-01-01
    • 2016-01-11
    相关资源
    最近更新 更多