【问题标题】:read() seems to go into infinite loopread() 似乎进入了无限循环
【发布时间】:2013-01-27 22:15:49
【问题描述】:

我正在尝试从套接字读取数据。出于某种我无法理解的原因,读取函数似乎进入了无限循环。我认为发生这种情况的原因是因为在使用 eclipse 进行调试时,调试器没有通过 read 函数。此外,当我使用终端运行程序时,它会永远运行。救命!!

附加信息:在 Linux 上运行,不确定是否与此问题有关,但我在程序中创建线程。

我想我应该提到的另一件事:第一次调用 read() 时,它按预期工作并读取套接字中的整个消息。当第二次再次调用 read() 时问题就开始了(当没有任何东西可以读取时)。我预计 read 会返回 0 来结束函数,但是 read 会进入无限循环。

这就是发生的一切:

read_write_res block_read_reply(int fd, void* buf, int max, int* read_size) {
int flag = 1;
if (read_size != NULL)
    *read_size = 0;
int i;
while (1) {
    i = read(fd, buf, max); /* HERE is where the debbuger gets stuck */
    if (i == 0 && flag == 1) //nothing to read
        continue;
    if (i == 0 && flag == 0)
        return READ_WRITE_SUCCESS;
    if (i < 0){
        return READ_WRITE_FAILURE;
    if (i > 0 && read_size != NULL)
        *read_size += i;
    }
    flag = 0;
    max -= i;
    buf = (char*) (buf) + i;
}
return READ_WRITE_SUCCESS;

}

【问题讨论】:

  • if (i == 0 &amp;&amp; flag == 1) continue; ... man read 是你的朋友。
  • "成功则返回读取的字节数(零表示文件结束)"
  • 请注意,对于 EAGAIN 和 EINTR 错误,您不应返回错误,而应重试。
  • @eyalm: EAGAIN 除非套接字是非阻塞的,否则不会发生,在这种情况下,立即重试不是你应该做的。 EINTR 通常根本不会发生(除非您安装了中断信号处理程序),如果发生了,是重试还是将其视为错误情况并不是那么明确。重试EINTR 会破坏中断信号处理程序的目的,在这种情况下,您可能应该使用SA_RESTART 安装它们...

标签: c linux


【解决方案1】:

如果read 返回 0,则表示您已达到文件结束状态。对于套接字或管道,这意味着将没有更多可读取的内容。曾经。所以在这种情况下执行continue;绝对不是你想做的。

【讨论】:

  • 上述函数是服务器程序的一部分。所以我在该行中输入的原因是为了防止服务器在任何客户端将命令放在那里之前从套接字读取。也就是说,服务器可能会在客户端发出任何请求之前运行一个小时,所以我希望服务器在套接字上“忙等待”,直到至少给出一个请求。无论如何,这不是程序冻结的地方。再次,它冻结在: i = read(fd, buf, max) 感谢您的回复。
  • @user2016436 无论如何你都必须解决这个问题。如果您仍然无法读取,则在修复此问题后 - 可能只是没有数据可读取。 read() 阻塞直到有。
  • @nos 在谷歌上几个小时后,确实似乎没有数据要读取,这使得 read() 阻塞。没有数据可读取时,如何防止调用 read()?
  • read() 将返回 EAGAIN 或 EWOULDBLOCK 如果您将套接字设置为非阻塞并且感觉不像立即读取数据。它也可以返回 EINTR,在这种情况下你应该重试。
  • @user2016436:这就是poll(或广泛使用但劣质的select函数)的用途。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 1970-01-01
  • 2021-01-26
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多