Nicht blockierende Eingabe (Konsole)
-
Hi,
sorry, dass ich das hier nach einem Monat immer noch pushen muss, aber ich habe für beide Probleme noch keine Lösung gefunden:
1. Kann ein select()-Server genauso schnell sein wie das Multithreadingäquivalent?
2. Wir krieg ich jetzt nicht-blockierende Eingabe ohne Zerhackstückselung der Ausgabe in der Konsole hin? Gar nicht?ChrisM
-
Hi,
bitte helft mir doch, auch wenn der Thread hier langsam (nicht nur euch) nervt, aber das kann doch nicht sein, dass hier noch keiner einen Server geschrieben hat, oder doch?
ChrisM
-
Ach komm, so schwer ist das doch garnicht.
Du machst mehrere Threads, einer verwaltet die Ausgabe, einer die Eingabe, einer den Rest. Der Ausgabethread schläft.Wenn jemand was ausgeben will, dann gibt er das was auszugeben ist an den Ausgabe-Thread (einfach irgendwo in nen Puffer reinhängen), dann weckt er den Ausgabethread auf. Und der schaut nach, ob die Konsole grad frei ist, falls ja markiert er sie als besetzt und gibt seine Daten aus, danach wieder freigeben und legt sich wieder schlafen.
Das solltest Du mit ner Semaphore machen, weil sonst evtl. Aufweck-Signale verloren gehen.
Sobald ne Eingabe kommt übernimmt die der Eingabethread und setzt die Konsole auf blockiert. Dann wird gewartet, bis Du mit Return bestätigst, dadurch gibst Du die Konsole wieder frei und weckst den Ausgabethread auf, ob er was zum Ausgeben hat in der Zwischenzeit.
Alternativ hätte ich auch noch ne viel einfachere Lösung:
Mach die Konsole nur als Anzeige und ne Eingabezeile.
Wenn also neue Messages kommen, dann werden die einfach angehängt und Deine Eingabezeile bleibt unten fest stehen. Erst wenn Du Enter drückst wird das ganze Ausgegeben und damit in die restlichen Meldungen eingereiht.
Aber wirklich portabel wird das wahrscheinlich auch nicht.MfG Jester
-
Hi,
ok, soweit ist das klar, vielleicht kann ich auf den Ausgabethread ja sogar verzichten.
Jetzt geht es nur noch darum, ob es sich lohnt oder ob es der Performance eher schadet, für jeden Client einen eigenen Thread zu machen. Leider kann ich nicht mal eben einen Test mit genug Clients durchführen, um das zu testen.
ChrisM
-
Hi,
gleich nochmal eine Frage zu Threading: Wie kann ich Multithreading portabel implementieren, ohne eine Lib zu verwenden?
Geht das überhaupt (vielleicht gibt's ja POSIX-Funktion...) oder muss ich das mit bedingter Compilierung lösen?
ChrisM
-
Es gibt ne POSIX-API für Threads, aber willkommen bei MS: Windows hat die AFAIK nicht implementiert. Also entweder doch ne Lib oder bedingte Kompilierung bzw. Eine Schnittstelle definieren und dann mehrmals implementieren.
Auf den Ausgabethread würd ich übrigens nicht verzichten, weil Dein Programm sonst, wenn es eine Ausgabe machen will und die Konsole gerade durch die Eingabe blockiert ist warten muß, bis es weiter gehen kann.
Du könnetst höchstens versuchen Ein/Ausgabe in einem Thread unterzubringen.
Das könnte auch eine ganze gute Lösung sein, zumal Du dann einige Synchronisationsprobleme los wirst.MfG Jester
-
Für Threads würde ich boost::thread nehmen (www.boost.org). Da man boost sowieso an allen Ecken und Enden brauchen kann, ist es IMHO kein sinnvolles Ziel, bei den Bibliotheken zu sparen.
Und ich habe schon Server geschrieben, allerdings hatten die keine Eingabe. Und wenn, dann waren es eh Windows-Anwendungen mit einer ListBox und einem Edit, und Multithreading bin ich mit asynchronen Sockets auch aus dem Weg gegangen. Bist du sicher, dass du all die Portabilität wirklich brauchst? Wenn eine plattformunabhängige Lösung mehr Arbeit ist als jeweils eine für alle Zielplattformen zu schreiben, dann kann mans auch sein lassen
-
Hi,
naja, portabel sollte es schon sein. Der Client muss ja net unter Linux laufen, aber der Server sollte das schon.
Aber das was ich jetzt noch momentan mache (mit select()), ist es ja quasi wie mit asynchronen Sockets. Nur bezweifle ich, dass das schnell genug ist.
Für die Threads werd' ich dann doch Boost verwenden, jetzt muss ich nur noch wissen, was schneller ist und dann geht es los:
- select() mit Timeout 0 (Polling)
- Thread für jede Verbindung und Blocking CallsChrisM
-
Ich weiß nicht ob es sinnvoll ist für jeden User einen Thread zu fahren. Das macht die Sache jedenfalls schwieriger. Wie wäre es mit einem Worker-Thread und eben einem oder zwei Threads für Ein/Ausgabe, die dann aber die meiste Zeit schlafen, also nur in den seltenen Fällen einer Ein/Ausgabe Rechenzeit benötigen. Damit ist es die meiste Zeit, als hättest Du nur den Workerthread laufen.
-
Hi,
ja, aber dann muss ich im Workerthread ja zwangsläufig select() oder asynchrone Sockets verwenden (eher select(), weil das portabel ist) und mir wurde gesagt, dass z.B. auch send() Zeit braucht und das wäre halt blöd, wenn dann immer der ganze Hauptthread in der Zeit nix anderes machen kann.
Nur weiß ich net, ob der Zeitverlust kleiner ist als der durch die Massen an Threads. (mit 100 Clients könnt ihr rechnen...)
ChrisM
-
hm, nochmal zu dem Zerstückelungsproblem, tut mir leid, wenn das mittlerweile nicht mehr gefragt ist,
aber in den Programmen, die ich kenne, hat man für die Eingabe ein eigenes Feld, die Ausgaben kommen in ein anderes Feld. Da kann dann auch nix zerstückelt werden...
-
Da wirst Du wohl mal ausprobieren müssen. Du könntest ja auch ein hybrides Modell bauen: Jeder Workerthread managed bis zu 10 Clients, immer wenn alle voll sind wird für den nächsten ein neuer Thread gestartet.
Dadurch kannst Du viele Clients bedienen und hast trotzdem nicht ganz so viele Threads.
-
Hi,
*** schrieb:
aber in den Programmen, die ich kenne, hat man für die Eingabe ein eigenes Feld, die Ausgaben kommen in ein anderes Feld. Da kann dann auch nix zerstückelt werden...
ja, aber wie macht man sowas, ohne cout/cin usw. neuzuschreiben?
ChrisM
-
Kann ein normales Linux wirklich *keine* asynchronen Sockets?! select ist eine der fragwürdig designtesten Funktionen, der ich je begegnet bin... (Ja, ich komme nicht viel rum
).
-
Hi,
was findest du an select() so schlecht? Ich find select() vom Prinzip her zum Pollen (also sofortige Rückkehr ohne Warten) gut geeignet, nur hab' ich halt oft gehört, dass es nicht grade schnell sein soll.
Ich werde jetzt vorerst bei select() bleiben und später dann schauen, ob ich doch Threads verwende.
ChrisM