Auch mit soc_poll() kann ein Programm mehrere Verbindungen gleichzeitig überwachen.
Der folgende Programmausschnitt skizziert die Verwendung von soc_poll():
#include <sys.socket.h> #include <sys.poll.h> ... struct pollfd fds[3]; int timeout = 0; unsigned long nfds = 3; fds[0].events = POLLIN; fds[1].events = POLLOUT fds[2].events = POLLIN; ... soc_poll(fds, nfds, timeout);
Die zu prüfenden Socket-Deskriptoren und Ereignisse werden in einem Array von Struktur-Elementen des Typs pollfd übergeben. fds ist ein Zeiger auf diesen Array. Mit nfds wird die Anzahl der Strukturelemente spezifiziert.
Im vorliegenden Beispiel sind dies die Deskriptoren 0...2 und die Ereignisse POLLIN bzw. POLLOUT. POLLIN steht für die Lesebereitschaft und POLLOUT für die Schreibbereitschaft des Socket.
Mit dem Parameter timeout wird festgelegt, wie sich die Funktion soc_poll() verhalten soll, wenn kein zu prüfendes Ereignis eingetreten ist:
Bei timeout = 0 prüft soc_poll() nur einmal alle angegebenen Deskriptoren auf das zu testende Ereignis. Danach kehrt die sock_poll() wieder zurück, unabhängig davon, ob die Prüfung erfolgreich war oder nicht.
Bei timeout > 0 wird eine Wartezeit in Sekunden angegeben. Während dieser Wartezeit blockiert soc_poll(), solange keines der zu testenden Ereignisse eintritt.
Bei timeout = -1 blockiert soc_poll() bis eines der zu testenden Ereignisse eintritt.
Der Returnwert von soc_poll() gibt die Menge der Treffer an, d.h. mindestens ein Bit ist im Rückgabefeld revents des jeweiligen Struktur-Elements pollfd gesetzt.
Struktur pollfd, wie sie in <sys.poll.h> deklariert ist:
struct pollfd { int fd; /* socket file descriptor to poll*/ short events; /* events on interest on fd*/ short revents; /* events that occured on fd */ };
Beispiel: Verwenden von soc_poll() zum Überprüfen auf anstehende Verbindungsanforderungen
Der folgende Programmcode entspricht dem vorhergehenden Beispiel, es wurde nur die Funktion select() durch soc_poll() ersetzt.
#include <sys.types.h> #include <stdlib.h> #include <sys.socket.h> #include <sys.poll.h> #include <netinet.in.h> #include <netdb.h> #include <stdio.h> #define TRUE 1 #define TESTPORT 5555 /* * Dieses Programm überprüft mit soc_poll(), ob jemand versucht, eine * Verbindung aufzubauen, und ruft dann accept() auf. */ main() { int sock; struct sockaddr_in server; struct sockaddr_in client; int clientlen; int msgsock; struct pollfd fds[1]; unsigned long nfds = 1; int timeout = 5; memset(&server,'\0',sizeof(server)); memset(&client,'\0',sizeof(client)); clientlen = sizeof(client); /* Initialisieren des Strukturarrays fds für die Abfrage der Lesebereitschaft des listen sockets */ fds[0].fd = 0; fds[0].events = POLLIN; fds[0].revents = 0; /* Socket erzeugen. */ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("opening stream socket"); exit(1); } /* Dem Socket unter Verwendung von Wildcards einen Namen zuordnen */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(TESTPORT); if (bind(sock, (struct sockaddr *)&server, sizeof server) < 0) { perror("binding stream socket"); exit(1); } /* Beginn der Annahme von Verbindungen. */ listen(sock, 5); do { fds[0].fd = sock; if ((soc_poll(fds, nfds, timeout)) <= 0){ perror("soc_poll"); continue; } else { if (fds[0].revents & POLLIN) { fds[0].revents = 0; msgsock = accept(sock, (struct sockaddr *)&client, &clientlen); if (msgsock >= 0) { /* Erfolgreiche Annahme des Verbindungsaufbauwunsches */ /* Folgeverarbeitung der Daten, die ueber diese Verbindung */ /* transferiert werden */ printf("Programmende nach erfolgreichem Verbindungsaufbau\n"); break; } else { /* Es ist ein Fehler aufgetreten */ /* Fehlermeldung und eventuell erneutes Warten auf einen */ /* Verbindungsaufbauwunsch */ printf("Programmende: Beim Verbindungsaufbau ist ein Fehler aufgetreten\n"); break; } } } } while (TRUE); exit(0); }