nicht blockierendes select()
-
Hallo, ich schreibe gerade ein Server/Client-Programm (eigentlich in C++, aber select gehört, glaube ich, hierher, oder?).
Um mehrere Clients behandeln zu können, verwende ichselect()
.
Aberselect()
blockiert, bis sich ein Client verbindet, oder eine Nachricht eintrifft, wie kann man alsoselect()
dazu bringen, einfach eine "0" zurückzugeben, wenn keine Daten vorliegen?mfg D3lta
-
Nein. Was soll select sein? Ich rate mal, dass du in Linux sockets machst.
-
Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89 und C99) in das Forum Linux/Unix verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
IIRC kannst Du den timeout auf 0 setzen.
-
SeppJ schrieb:
Nein. Was soll select sein? Ich rate mal, dass du in Linux sockets machst.
Richtig geraten
select()
sucht in Deskriptormengen nach lesbaren Deskriptoren und gibt die Anzahl zurück (so blockieren accpet() und recv() nicht dauernd, aber dafür blockiertselect()
. Aber ich suche einen Weg, das auch noch zu beseitigen...mfg D3lta
EDIT: Was heißt "IIRC"?
EDIT: Hat sich erledigt (Ich hatte den Timeout schon auf null, habe aber nicht gemerkt, dass die Endlosschleife durchliefmfg D3lta
-
Die Frage ist, was Du davon hast. Immerhin ist select() genau dafür da auf Ereignisse zu warten und weniger um mal kurz "nachzufühlen".
Verständlich ist Dein Interesse aber zB dann, wenn Du gewissermaßen nebenläufig zu den Sockets noch etwas tun willst.
Beispiel: Du betreibst mit select() einen Relay-Server der Nachrichten zwischen den Clients übermittelt (Chat). Nun willst Du aber administrativ, per Konsole auf den Server zugreifen können während dieser läuft. Denkbar sind zB Befehle wzB "status", "say", "quit" o.Ä.
Wie SG1 richtig angemerkt hat, kannst Du hierfür den timeout (struct timeval*) setzen. Achtung: Übergibst Du nur NULL/0, so blockiert select() so lange bis etwas passiert. Du musst ein neues timeval Objekt anlegen und dann tv_sec und tv_usec entsprechend setzen.
Allerdings ist das nicht wirklich schön, denn die CPU-Belastung geht in die Höhe.
Sinnvoller ist es den stdin Deskriptor ebenfalls mit select() auf Lesbarkeit prüfen zu lassen. Normalerweise ist die fdID hierfür die 0 (hier mehr dazu). Du brauchst also etwas wie FD_SET(0,&my_set) bzw. vielleicht sinnvoller FD_SET(stdin,&my_set) - Du musst dann nur darauf aufpassen, dass stdin kein Socket ist und stdin gesondert abfragen.
Ich habe jetzt stark vermutet, dass Du genau soetwas willst.
Sollte dem nicht so sein, konkretisiere doch Dein Vorhaben ein wenig mehr.Herzliche Grüße,
Max
-
Ich habe z.b. select in einer GUI Anwendung am werkeln, und um auf Threads zu verzichten, lasse ich es 30mal pro Sekunde aus der GUI als Idle-Callback aufrufen und mit 20ms blockend warten. CPU Auslastung ist dann bei Null und es ist für die Zwecke der Anwendung ausreichend performant. Und der Verzicht auf Threads und synchronisieren und bla, ist grandios!
-
ichwillwiederinsbett schrieb:
Ich habe z.b. select in einer GUI Anwendung am werkeln, und um auf Threads zu verzichten, lasse ich es 30mal pro Sekunde aus der GUI als Idle-Callback aufrufen und mit 20ms blockend warten. CPU Auslastung ist dann bei Null und es ist für die Zwecke der Anwendung ausreichend performant. Und der Verzicht auf Threads und synchronisieren und bla, ist grandios!
GUI-Libraries haben doch in der Regel schon eine Event-Loop. Da kann man in der Regel auch eigene Sockets/FD reinhängen. Hat den Vorteil, dass es einfacher zu realisieren ist, nicht auf idle warten muss und ggf. was besseres als select nutzt (zB epoll unter Linux).
zB. GTK+ bietet dafür g_source_add_poll und Qt hat dafür QAbstractEventDispatcher.
-
Jepp, aber in python arbeite ich mit GTK und gevent. Und gevent lässt sich leider nicht so direkt in den glib-eventloop integrieren. also mach ich einfach ein sleep(0.03) im Idle-Callback, um die Kontrolle kurz an gevent zu übergeben.