【问题标题】:blocking recv() that receives no data (TCP)阻塞不接收数据的 recv() (TCP)
【发布时间】:2013-04-03 00:18:40
【问题描述】:

我正在尝试使用 C 系统调用编写一个简单的服务器,该服务器从未知客户端获取未知字节流,并根据客户端输入执行特定操作。例如,客户端将发送命令“乘 2 2”,服务器将数字相乘并返回结果。

为了避免服务器在客户端写入之前读取错误,我有一个阻塞的 recv() 调用来等待使用 MSG_PEEK 的任何数据。当 recv 检测到要读取的数据时,我会转到非阻塞 recv() 逐字节读取流。

除了客户端不发送数据的极端情况(即 write(socket, "", 0); )外,一切正常。我想知道如何准确检测到没有数据的消息已发送。在这种情况下,recv() 会永远阻塞。

另外,这篇文章几乎总结了我的问题,但它并没有提出检测大小为 0 数据包的方法。 What value will recv() return if it receives a valid TCP packet with payload sized 0

【问题讨论】:

  • write(socket, "", 0) 在像 TCP 这样的基于流的协议中没有意义:(一个 1000 字节数据包后跟一个 0 字节数据包)、单个 1000 字节数据包之间没有语义差异,或两个 500 字节的数据包,因为它们都是 1000 字节的单个数据流。
  • 你没有“消息”之类的东西,怎么会有“没有数据的消息”?!只有当你有某种支持消息的协议时,你才能拥有消息。您使用什么协议来支持消息?我没有看到。

标签: c sockets tcp system-calls recv


【解决方案1】:

在send/recv 级别使用 TCP 时,您不知道进入流的数据包流量。当您通过 TCP 流发送非零字节数时,序列号会增加字节数。这就是双方在成功交换数据方面知道对方在哪里的方式。发送具有相同序列号的多个数据包并不意味着客户端做了任何事情(例如您的write(s, "", 0) 示例),它只是意味着客户端想要传达一些其他信息(例如,数据流的 ACK另一种方法)。在流级别操作时,您无法直接看到重传、重复 ACK 或其他类似异常情况。

你链接的答案说的差不多。

【讨论】:

    【解决方案2】:

    除了客户端不发送数据的极端情况(即 write(socket, "", 0); )之外,一切正常。

    write(socket, "", 0) 一开始就不是发送。它只是一个本地 API 调用,在网络上什么都不做。

    我想知道如何准确检测到没有数据的消息已发送。

    没有消息被发送,所以没有什么可检测的。

    在这种情况下,recv() 永远阻塞。

    我同意。

    【讨论】:

      【解决方案3】:

      我有一个阻塞的 recv() 调用来等待使用 MSG_PEEK 的任何数据。当 recv 检测到要读取的数据时,我会转到非阻塞 recv() 逐字节读取流。

      您应该使用select()、poll() 或epoll() 来检测数据何时到达,然后调用recv() 来读取它,而不是使用recv(MSG_PEEK)。

      【讨论】:

      • 无关紧要。他在询问零长度写入。这里没有任何东西可以回答这个问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多