Nicht blockierende Eingabe (Konsole)



  • Hi,

    ich bin grade beim Schreiben eines kleinen Servers, der als Konsolenanwendung geschrieben wird.

    Problem ist nur, dass man während der Server läuft auch Eingaben machen können soll (halt Befehle um Leute zu kicken, den Server zu beenden, Statistiken anzuzeigen usw.), nur blockt cin ja, bis die Eingabe erfolgt ist.

    Leider hab ich auf dem Gebiet (Konsole) noch nicht so viel Erfahrung gesammelt, aber ihr verratet mir jetzt bestimmt, wie das geht, schließlich kann das ja nahezu jeder Konsolenserver. 🙂

    Ansonsten würde ich das ganze mit Threads machen, aber ich denke, das ist etwas arg viel Overhead, oder? Und vor allem wird die Ausgabe bestimmt zerhackstückelt, wenn eine Ausgabe erfolgt, während der User etwas tippt...

    ChrisM



  • Mit select() auf stdin. Zumindest unter Unix wo Sockets auch Dateien sind.



  • http://www.c-plusplus.net/forum/viewtopic.php?t=39320
    kbhit vielleicht aber pass nicht recht ins c++ standard forum



  • Hi,

    geht es nicht anders? Weil nur die erste Funktion ist portabel, liefert aber nur ein Zeichen...

    Nehmen wir doch mal einen bekanntes Spieleserver, z.B. einen Half-Life- (CS-), einen UT- oder einen Battlefield-Dedicatedserver. Bei denen geht das doch bestimmt auch, wie machen die das?

    ChrisM



  • Die werden das wohl auch plattformabhängig gelöst haben.



  • Man kann auch mehrere Ausführungsthreads nehmen. Aber die gehen auch nicht portabel... Ich glaube, im Rahmen des C++-Standards kommst du nicht weit 😉



  • Hi,

    schade. 😞

    ChrisM





  • also ich hab das über Threads gelöst
    das ist sowieso die beste Methode.

    Die konsole hat den Hauptthread.

    Der Server (accept) hat nen eigenen thread,
    und jeder Client hat wiederum nen thread.



  • operator void schrieb:

    Man kann auch mehrere Ausführungsthreads nehmen. Aber die gehen auch nicht portabel... Ich glaube, im Rahmen des C++-Standards kommst du nicht weit 😉

    man kann das ganze portable machen mit boost oder ACE



  • Hi,

    danke für eure Antworten! 🙂

    Irgendwie weiß ich jetzt auch nicht mehr recht, was ich nehmen soll.
    Das mit select() gefällt mir natürlich besser als die Thread-Lösung, weil 1. schneller, 2. einfacher (:D) und 3. ich dann nicht auf Threadsicherheit achten muss, allerdings habe ich beim select() das Problem, dass wenn während gerade eine Eingabe gemacht wird, die aktuelle Eingabe zerstückelt wird (aber das Problem hätte ich bei den Threads ja vermutlich auch, es sei denn, ich erstelle zwei Konsolen, aber das wird ja vermutlich nicht portabel gehen, oder?).

    Was würdet ihr nehmen?

    Oder schaut euch mal den Half-Life-Server an, falls ihr Half-Life installiert habt? Einfach nur die hlds.exe starten... (ohne Parameter)

    ChrisM



  • Ich verstehe nicht ganz was dein Problem ist. Du meinst wohl wenn eine Ausgabe kommt, während du tippst, dass dann die Eingabe zerhackstückelt wird oder?



  • Hi,

    genau! Nehmen wir an, ich möchte den Befehl status tippen.

    Beispiel:

    Server aktiv...
    Spieler ist gejoint...
    sta <- jetzt habe ich sta von status schon getippt, genau in dem Moment kommt eine weitere Meldung:
    Spieler ist gequittet...
    tus <- und hier hab ich weitergetippt!

    Ich könnte natürlich sämtliche Ausgabe anhalten, während ein Befehl eingegeben wird, aber das ist alles andere als toll. 😞

    Oder ich mache die Konsole ohne Eingabemöglichkeit und der Server wird mit einem Remote Tool über eine localhost-Verbindung verwaltet (vieeeeel Arbeit!).

    ChrisM



  • ChrisM schrieb:

    Hi,

    danke für eure Antworten! 🙂

    Irgendwie weiß ich jetzt auch nicht mehr recht, was ich nehmen soll.
    Das mit select() gefällt mir natürlich besser als die Thread-Lösung, weil 1. schneller, 2. einfacher (:D) und 3. ich dann nicht auf Threadsicherheit achten muss, allerdings habe ich beim select() das Problem, dass wenn während gerade eine Eingabe gemacht wird, die aktuelle Eingabe zerstückelt wird (aber das Problem hätte ich bei den Threads ja vermutlich auch, es sei denn, ich erstelle zwei Konsolen, aber das wird ja vermutlich nicht portabel gehen, oder?).

    Was würdet ihr nehmen?

    Oder schaut euch mal den Half-Life-Server an, falls ihr Half-Life installiert habt? Einfach nur die hlds.exe starten... (ohne Parameter)

    ChrisM

    select blockiert deinen Hauptthread. da kannst du keine eingabe mehr machen.
    und nein die threadlösung ist nicht langsamer, im Gegenteil - schließlich ist Windows eine Multithreadumgebung.
    Heute spiele und Chatserver würden ohne Mutlithreadumgebung nicht soschnell laufen, wie sie sind.
    Wenn schon 5 Leute im Halflife spiel wären, und nur ein Thread mit select auf die einkommenden daten warten würde - dann hätte wohl jeder mindestens einen 200er ping!
    Glaub mir ,Threads sind gewöhnungsbedürftig und man muss sich ein Syncronisationschema ausdenken, aber sie sind sehr leistungsstark.



  • Hi,

    bisher hatte ich es eigentlich genau so vor. 😮
    Ich wollte einen den Server mit nur einem Thread machen, der mit select() die ganze Clientliste abruft und überall die neuen Messages, falls vorhanden, verarbeitet. select() würde bei mir natürlich nicht blocken, weil ich mit UDP arbeite, d.h. nicht an einer spezifischen Verbindung auf Daten warte.

    Nach deinem Konzept würde ich das dann aber so machen, oder?
    Ich habe viele kleine Threads, die nur jeden Frame gefragt werden, ob was angekommen ist und jeden Frame bzw. regelmäßig ein Datenpaket an den Client schicken und einen großen Hauptthread, der halt die ganze Physik, die Kämpfe, den Chat und halt die ganzen Serverfunktionen ausmacht. (+ den Thread für die Konsoleneingabe :D)

    ChrisM



  • Hi,

    *push*

    ChrisM



  • Dezipaitor schrieb:

    select blockiert deinen Hauptthread. da kannst du keine eingabe mehr machen.

    select hat einen timeout-Parameter, den man AFAIK auch auf 0 stellen kann. Dann pollt es. Man kann auch nichtblockierende Sockets nehmen, das ist imho bequemer als das kreplige select. Man kann also auch singlethreaded effiziente und schöne Server basteln. Alles in mehrere Threads aufteilen macht die Sache nicht automatisch effizienter, vor allem nicht auf einem Prozessor...
    Das einzige Problem ist nach wie vor, dass sich die komplette Serverberechnung schlecht mit dem blockierenden Konsoleninput vereinbaren lässt. Ich würde ein Konsolenfenster per WinAPI bauen. Vielleicht kann man auch die Konsoleneingabe per _kbhit selber nachbauen, aber das klingt eklig 🙂



  • Hi,

    wenn das mit dem Timeout wirklich geht, dürfte der Server ja auf Maschinen ohne Hyper Threading dann ja auch nicht langsamer sein, eher schneller, weil die Synchronisation wegfällt, oder?

    Aber asynchrone Sockets sind AFAIK nicht portabel.

    ChrisM



  • Hi,

    *push*

    Wo sind denn die ganzen Experten? Bei allen möglichen Fragen habt ihr eine perfekte Lösung parat und hier habt ihr keinen Vorschlag?

    ChrisM



  • ChrisM schrieb:

    Aber asynchrone Sockets sind AFAIK nicht portabel.

    und was ist mit ACE?


Anmelden zum Antworten