zmq_poll 的具体工作原理是什么?在哪些情况下我需要它?

How does the zmq_poll work in details and in which cases do I need it?

这个api很模糊所以想在这里问一下,zmq_poll是怎么工作的

假设我们有这段代码:

//set timerValue here

1: items[0].socket = server_socket;
2: items[0].events = ZMQ_POLLIN;
3: items[0].fd = timerfd_create(CLOCK_REALTIME, 0);
4:
5: timerfd_settime(items[0].fd, 0, &timerValue, NULL);
6:
7: zmq_poll(items, 1, -1);
8:
9: if(items[0].revents & ZMQ_POLLIN){
10:    ...
11: }

假设计时器运行一分钟然后超时。如果我们通过这段代码,我们会设置一个套接字和文件描述符。 api 表示:

For each zmq_pollitem_t item, zmq_poll() shall examine either the ØMQ socket referenced by socket or the standard socket specified by the file descriptor fd, for the event(s) specified in events. If both socket and fd are set in a single zmq_pollitem_t, the ØMQ socket referenced by socket shall take precedence and the value of fd shall be ignored. http://api.zeromq.org/2-1:zmq-poll

  1. 设置套接字和文件描述符到底意味着什么?它是否主要等待客户端发送消息的套接字,如果它没有收到任何事件,它会等待计时器吗?

  2. 如果我们调用第 7 行,它是否会在第 7 行等待,只要计时器已启动或收到事件?或者我是否必须执行一个 while(1) 循环来检查第 9 行中的 if 语句?

  3. 在哪些情况下您需要多个项目? (如果要设置多个定时器?)

那么基本上 zmq_poll 与 fd and/or 套接字的行为如何?等待过程在哪里?我认为轮询类似于中断(或等待?)。我对这一切有点困惑。

大多数操作系统都有一个系统调用来有效地等待对象上的事件。在 Linux 上,此系统调用是 poll(),对象是文件描述符。

因为 ZeroMQ 套接字不是文件描述符,所以不能将 poll() 与 ZeroMQ 套接字一起使用。这就是为什么有 zmq_poll()。作为额外的奖励,zmq_poll() 允许您等待 ZeroMQ 套接字 文件描述符上的事件。这对许多程序很有用。例如,如果你有一个交互式程序,你想等待 ZeroMQ 套接字上的事件 来自标准输入的键盘输入,这是一个文件描述符。

关于您的代码和问题:

  • zmq_poll() 有超时参数。无需自己创建定时器。
  • 您只能设置 .socket zmq_pollitem_t.fd 成员之一,但不能同时设置两者。将另一个设置为 0。如果同时设置,ZeroMQ 将忽略 .fd 成员。
  • 当您调用 zmq_poll() 时,您的程序将阻塞直到 zmq_poll() returns。 zmq_poll() returns 当事件发生在 zmq_pollitem_t 之一 超时到期时。
  • 您可以根据需要等待任意数量的 zmq_pollitem_t。这取决于您的程序。例如,服务器可能处理多个连接,您为每个连接创建一个 zmq_pollitem_t

以下示例代码等待 ZeroMQ 套接字和文件描述符。

void wait_for_socket_and_fd(void* sock, int fd, long timeout)
{
  // wait for two objects
  zmq_pollitem_t items[2];

  // wait for ZeroMQ socket...
  items[0].socket = sock;
  items[0].fd = 0;
  items[0].events = ZMQ_POLLIN;

  // ...and wait for fd
  items[1].socket = NULL;
  items[1].fd = fd;
  items[1].events = ZMQ_POLLIN;

  // block until event occurs or timeout expires
  int ret =  zmq_poll(items, sizeof(items) / sizeof(items[0]), timeout);
  if (ret > 0)
  {
    // event occurred
    if (items[0].revents != 0)
    {
      // event occurred on sock, process it
    }
    if (items[1].revents != 0)
    {
      // event occurred on fd, process it
    }
  }
  else if (ret == 0)
  {
    // timeout expired, do something
  }
  else
  {
    // error occurred, handle it
  }
}