Как работает zmq_poll в деталях и в каких случаях он мне нужен? - PullRequest
0 голосов
/ 06 августа 2020

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: }

И допустим, что таймер работает минуту и ​​тайм-аут. Если мы go через этот код, мы устанавливаем сокет и дескриптор файла. API говорит:

Для каждого элемента zmq_pollitem_t zmq_poll () проверяет либо сокет ØMQ, на который ссылается сокет, либо стандартный сокет, указанный файловым дескриптором fd, на предмет событий, указанных в events . Если и socket, и fd установлены в одном zmq_pollitem_t, сокет ØMQ, на который ссылается socket, должен иметь приоритет, а значение fd должно игнорироваться. http://api.zeromq.org/2-1: zmq-poll

  1. Что именно означает установка сокета и дескриптора файла? Ожидает ли он в первую очередь сокета, чтобы клиент отправил сообщение, и если он не получит никакого события, он ждет таймера?

  2. Если мы вызываем строку 7, он ждет в строке 7 до тех пор, пока таймер истечет или произойдет событие? Или мне нужно реализовать while (1) l oop, чтобы каждый раз проверять оператор if в строке 9?

  3. В каких случаях вам понадобится несколько элементов? (Если вы хотите установить несколько таймеров?)

Итак, в основном, как zmq_poll ведет себя с fd и / или сокетом? Где процесс ожидания? Я думал, что опрос - это то же самое, что прерывать (или ждать?). Меня это все немного смущает.

1 Ответ

1 голос
/ 06 августа 2020

В большинстве операционных систем есть системный вызов для эффективного ожидания событий на объектах. На Linux этот системный вызов - poll(), а объекты являются дескрипторами файлов.

Поскольку сокеты ZeroMQ не являются дескрипторами файлов, вы не можете использовать poll() с сокетами ZeroMQ. Поэтому стоит zmq_poll(). В качестве дополнительного бонуса zmq_poll() позволяет вам ждать событий в файловых дескрипторах сокетов ZeroMQ и . Это полезно для многих программ. Например, если у вас есть интерактивная программа, вы хотите дождаться событий на сокетах ZeroMQ и ввод с клавиатуры со стандартного ввода, который является дескриптором файла.

Относительно вашего кода и ваших вопросов :

  • zmq_poll() имеет аргумент тайм-аута. Нет необходимости создавать таймер самостоятельно.
  • Вы должны установить только .socket или член .fd из zmq_pollitem_t, но не оба сразу. Установите другое значение 0. Если вы установите оба параметра, ZeroMQ будет игнорировать элемент .fd.
  • Когда вы вызываете zmq_poll(), ваша программа будет блокироваться до тех пор, пока не вернется zmq_poll(). zmq_poll() возвращает либо, когда событие происходит на одном из zmq_pollitem_t s , либо , когда истекает время ожидания.
  • Вы можете подождать столько zmq_pollitem_t s, сколько вам нужно. Это зависит от вашей программы. Например, сервер может обрабатывать несколько подключений, и вы создаете 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
  }
}
...