尽管指定了超时,但是poll()无限期地等待

时间:2019-05-08 10:07:28

标签: c server client polling unix-socket

我正在编写一个C客户机-服务器程序,其中客户机必须从服务器接收大量数据。由于我希望我的客户端在服务器出问题时(例如,在发送数据时停止运行),不要无限期地在.replace(/\"/g, "")上等待,因此我选择使用{ linux man page

我的代码如下:

{JSON.stringify(lconfigInfo.sql[configInfoKey]).replace(/\"/g, "")}

其中recv()是与套接字关联的文件描述符,poll()设置为5秒,由于我想读取数据,因此我将while (...) { struct pollfd fds; fds.fd = sock; fds.events = POLLIN; retry: r = poll(&fds, 1, TIMEOUT*1000); if (r == -1 && errno == EINTR) goto retry; else if (r == -1) err_sys("poll() failed"); else if (r == 0) err_sys("timeout expired"); recv(...) } 指定为事件。

问题

据人:

  

timeout参数指定poll()的毫秒数          应该阻止等待文件描述符准备就绪。通话          会一直阻塞,直到:

sock

但是,即使我在停止服务器后立即超时(我使用valgrind),程序仍在TIMEOUT函数上无限期地阻塞。我还尝试将事件设置为POLLIN(以适应某些特殊情况),但是没有用。我多次阅读了文档,但不知道是什么原因导致了这个问题。

其他信息

我正在使用Xubuntu 18.04,gcc版本7.4.0,目标x86_64

1 个答案:

答案 0 :(得分:1)

即使没有可读取的数据,您的代码也会无条件地调用recv()。实际上,如果fds.revents没有返回错误/超时,您将完全忽略poll()字段。

您的循环应如下所示:

struct pollfd fds;
fds.fd = sock;
fds.events = POLLIN;

do {
  r = poll(&fds, 1, TIMEOUT*1000);
  if (r == -1) {
    if (errno == EINTR) continue;
    perror("poll() failed");
    break;
  }
  else if (r == 0) {
    printf("timeout expired");
    break;
  }
  else if (fds.revents & POLLIN) {
    r = recv(...);
    if (r < 0) {
      perror("recv() failed");
      break;
    }
    else if (r == 0) {
      printf("socket disconnected\n");
      break;
    }
    else {
      // process data as needed...
    }
  }
  else if (fds.revents & (POLLERR | POLLNVAL)) {
    printf("socket error\n");
    break;
  }
}
while (1);

close(sock);