Опросить несколько сокетов одновременно
- Прототип
-
#include <sys/poll.h>
int poll(struct pollfd *ufds, unsigned int nfds, int
timeout);
- Описание
-
Эта функция очень похожа на select() в том, что обе они проверяют набор дескрипторов на события, типа входящих данных, готовых к recv(), сокетов, готовых к send(), ошибок и т.п.
Ты передаешь массив из nfds структур pollfd в ufds, а также таймаут в миллисекундах (в 1 секунде 1000 миллисекунд.) Если не произойдет никаких событий до истечения таймаута, poll() завершится. timeout может быть отрицательным - тогда poll() будешь ждать вечно.
Каждый элемент массива структур pollfd описывает один дескриптор сокета, и содержит такие поля:
struct pollfd {
int fd; // номер дескриптора
short events; // флаги событий, за которыми нужно следить
short revents; // после вызова poll(), флаги произошедших событий
};
|
Перед вызовом poll(), запиши в fd дескриптор сокета (если fd будет отрицательным, этот элемент массива проигнорируется и поле revents будет равно нулю) и собери поле events логическим сложением следующи макросов:
POLLIN |
Сообщи, когда в сокете есть входящие данные |
POLLOUT |
Сообщи, когда в сокет можно слать данные (без блокирования) |
POLLPRI |
Сообщи, когда в сокете появятся внепотоковые данные (out-of-band). |
После вызова poll(), поле revents будет содержать логическую сумму произошедших событий, плюс следующих флагов:
POLLERR |
Произошла ошибка. |
POLLHUP |
Удаленная сторона закрыла соединение. |
POLLNVAL |
Сокет fd не готов - может, он не инициализирован? |
- Возвращаемое значение
-
Возвращает количество элементов в массиве ufds, в которых произошли события; если функция завершилась по таймауту, она вернет ноль. Если произошла ошибка, она вернет -1 и сохранит номер ошибки вerrno
- Пример
-
int s1, s2;
int rv;
char buf1[256], buf2[256];
struct pollfd ufds[2];
s1 = socket(PF_INET, SOCK_STREAM, 0);
s2 = socket(PF_INET, SOCK_STREAM, 0);
// здесь мы соединяем оба сокета с серверами
//connect(s1, ...)...
//connect(s2, ...)...
// собираем массив дескрипторов
//
// в этом примере мы хотим узнать, есть ли обычные или
// внепотоковые данные, готовые к recv()...
ufds[0].fd = s1;
ufds[0].events = POLLIN | POLLPRI; // обычные и внепотоковые
ufds[1] = s2;
ufds[1].events = POLLIN; // только обычные
// ждем событий, таймаут 3.5 секунды
rv = poll(ufds, 2, 3500);
if (rv == -1) {
perror("poll"); // произошла ошибка в poll()
} else if (rv == 0) {
printf("Таймаут! За 3.5 секунды данные не поступали.\n");
} else {
// проверяем события на s1:
if (ufds[0].revents & POLLIN) {
recv(s1, buf1, sizeof(buf1), 0); // получаем обычные данные
}
if (ufds[0].revents & POLLPRI) {
recv(s1, buf1, sizeof(buf1), MSG_OOB); // внепотоковые данные
}
// проверяем события на s2:
if (ufds[1].revents & POLLIN) {
recv(s1, buf2, sizeof(buf2), 0);
}
}
|
- См. также
-
select()
|