#include <sys/poll.h> int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
struct pollfd {
int fd; /* deskryptor */
short events; /* zdarzenia do monitorowania */
short revents; /* zdarzenia, które zaszly */
};
Pola events oraz revents mogą przyjmować m.in. takie wartośći:
Pole events zawiera warunki, które chcemy sprawdzać na danym deskryptorze fd. Natomiast pole revents jest wypełniane przez funkcję podczas powrotu. Zawiera ono warunki, które odblokowały funkcję.
Szybki przykład:
struct pollfd pfd[2];
pfd[0].fd = 0;
pfd[0].events = POLLIN;
pfd[0].revents = 0;
pfd[1].fd = 1;
pfd[1].events = POLLOUT;
pfd[1].revents = 0;
switch (poll (pfd, 2, 10000))
{
case -1:
{
perror ("poll()");
exit (1);
}
case 0:
{
printf ("Limit czasowy uplynal.\n");
exit (2);
}
default:
{
if (pfd[0].revents == POLLIN || pfd[1].revents == POLLOUT)
{
printf ("Jeden z deskryptorow zmienil stan.\n");
exit (0);
}
else
{
printf ("Blad.\n");
exit (3);
}
}
}
}
OK ale w jaki sposób zaprzęgnąć funkcje przepytujące do rozwiązania problemu
nasłuchu na kilku gniazdach naraz ? Robi się to w ten sposób;
/* Tworzymy gniazda (socket()) */
....
/* Każde z gniazd przestawiamy w tryb nieblokujący w ten sposób */
fcntl (d, F_SETFL, O_NONBLOCK);
/* Zmuszamy gniazda do nasłuchu (listen()) */
...
/* Wchodzimy do głównej pętli obsługującej połączenia nadchodzące */
while (1) {
FD_SET(d, &fds); /* Tą operację powtarzamy dla każdego gniazda */
...
/* Dopiero w tym miejscu wykonywanie programu zostanie wstrzymane. */
/* Funkcja select() nie zwróci bowiem sterowania dopóki któreś z */
/* gniazd nie zmieni swego stanu, co będzie oznaczalo, że */
/* najprawdopodobniej dobija sie do nas jakiś klient. */
ret = select(..., fds, ..., ..., ...);
/* Jeśli dotarliśmy do tego miejsca to znaczy, że na KTÓRYMŚ z */
/* gniazd oczekuje klient do obsłużenia. */
if (ret) {
for (...) { /* W pętli sprawdzamy, KTÓRE gniazdo jest gotowe */
if (ISSET(d)) {
accept (d, ...);
obsłuż_połączenie (d);
}
}
} else printf ("Upłynął limit czasowy.");
}
Powyższe rozwiązanie będzie spełniało swoje zadanie ale nadal nie jest idealne. Zauważyliśmy pewnie, że w pewnym momencie program jest mimo wszystko wstrzymywany na bliżej nieokreślony czas (select()). Oczekuje on bezczynnnie na nadejście połączenia. Byłoby dużo lepiej gdybyśmy mogli w tym czasie robić inne rzeczy. Taką możliwość zapewni nam połączenie gniazd nieblokujących z obsługą sygnałów.