Wie Sockets mit Timeout realisieren?
-
Hallo,
ich beschäftige mich z.Z. damit, einen kleine Konsolenchat in C++ zu schreiben. Ein verbindender Client soll innerhalb einer bestimmten Zeit (sagen wir mal 5 Sekunden) einen bestimmten Login-String angenommen seinen Nickname senden. Hierzu verwende ich diese Funktion:
char strMsg[BUFSIZE] = ""; int retval = 0; retval = recv(tcpSock,&strMsg,sizeof(strMsg),0);
Durch die Funktion recv wird ja der gesamte Programmablauf aufgehalten. Ich habe bereits über SO_RCVTIMEO im Zusammenhang mit setsockopt() gelesen, um dem recv-Command einen Timout zu geben. Leider habe ich dies (genauso wie die Non-Blocking Sockets) noch nicht wirklich hinbekommen.
Welche Methode sollte man für so etwas verwenden? Einen Socket-Timeout oder die Zeit manuell durch Schleifen und Non-Blocking Sockets stoppen? Wie macht man sowas am geschicktesten?
Danke,
Blu-Ray
-
Das Stichwort lautet
select
. So müsste das ganze in etwa aussehen:
// _F_ile-_D_escriptor-Set anlegen fd_set fds; FD_ZERO (&fds); FD_SET (client_socket, &fds); // Struktur für Zeit füllen struct timeval tv; tv.tv_sec = 5; // Zeit in Sekunden tv.tv_usec = 0; // Zeit in Microsekunden (nicht Millisekunden!) int rc = select (client_socket + 1, &fds, NULL, NULL, &tv); if (rc < 0) { // Fehler } else if (rc == 0) { // in der angegebenen Zeit nichts passiert } else { // irgendwas ist passiert if (FD_ISSET (client_socket, &fds)) { // Daten sind angekommen und können mit recv nicht-blockierend abgeholt werden } }
Mit FD_SET kannst du auch weitere Sockets (bestehende Verbindungen und auch Server-Sockets), Dateien und Pipes (half-duplex Pipes, stdin, ...) in das Set packen. Wenn select zurück kehrt, kannst du mit FD_ISSET alle File Deskriptoren prüfen und gucken, auf welchem was passiert ist.
-
@devkid
lieber epoll als select oder libevent/boost::asio, wenn es portabel sein soll.
-
Huh? Also von epoll hör ich gerade das erste Mal, scheint aber interessant zu sein.
Aber warum nicht select? Portabel ist das auch. Und für Anfänger scheint mir das auch einfach zu sein. Boost... naja. :p
-
ich finde epoll nicht nur einfacher, es ist auch einfach viel viel schneller und flexibler
-
Epoll ist platformabhängig oder? Gibt es davon eine unabhängige Funktion?
Ich werde zuerst mal die Lösung von devkid ausprobieren. Vielen Dank!
-
Blu-Ray schrieb:
Epoll ist platformabhängig oder?
Korrekt.
Blu-Ray schrieb:
Gibt es davon eine unabhängige Funktion?
select
-
Blu-Ray schrieb:
Epoll ist platformabhängig oder? Gibt es davon eine unabhängige Funktion?
Ich werde zuerst mal die Lösung von devkid ausprobieren. Vielen Dank!jein. manche unices haben /dev/poll und freebsd hat kqueue. eine plattformunabhängige, native api gibt es nicht.
-
Blu-Ray schrieb:
Epoll ist platformabhängig oder? Gibt es davon eine unabhängige Funktion?
Ich werde zuerst mal die Lösung von devkid ausprobieren. Vielen Dank!Naja entweder select oder was auch sehr nett sein soll ist libevent.