Предыдущая | Оглавление | Следующая |
Опросить несколько сокетов одновременно
#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); } } |
Предыдущая | Оглавление | Следующая |