Nicht blockierende Eingabe (Konsole)



  • 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?



  • Hi,

    Gegenfrage: Was ist ACE?

    Ich kenn zwar ACE als Kompressionsalgorithmus, aber das hat hiermit ja wohl nichts zu tun.

    Ist das eine Cross-Platformlib für Sockets?

    Aber jetzt noch eine Frage: Kann auch ein Singlethreadedserver mit select() bzw. asynchronen Sockets schnell genug sein oder muss es wirklich Multithreading sein?

    ChrisM



  • The ADAPTIVE Communication Environment (ACE) is a freely available, open-source object-oriented (OO) framework that implements many core patterns for concurrent communication software. ACE provides a rich set of reusable C++ wrapper facades and framework components that perform common communication software tasks across a range of OS platforms. The communication software tasks provided by ACE include event demultiplexing and event handler dispatching, signal handling, service initialization, interprocess communication, shared memory management, message routing, dynamic (re)configuration of distributed services, concurrent execution and synchronization.

    ACE is targeted for developers of high-performance and real-time communication services and applications. It simplifies the development of OO network applications and services that utilize interprocess communication, event demultiplexing, explicit dynamic linking, and concurrency. In addition, ACE automates system configuration and reconfiguration by dynamically linking services into applications at run-time and executing these services in one or more processes or threads.

    http://www.cs.wustl.edu/~schmidt/ACE.html



  • Hi,

    ich muss sagen, das Teil sieht ja richtig gut aus und scheint mir auch noch bei einigem mehr zu helfen als nur bei asynchronen Sockets.

    Nur weiß ich jetzt immer noch nicht, ob der Speed dann reicht oder ob ich, wenn ich vernünftige Pings haben will, auch bei hundert oder mehr Spielern, doch mehrere Threads verwenden muss. Denn ich habe keine Lust jetzt drauflos zu coden und dann am Ende festzustellen, dass ich alles nochmal umschreiben muss. 😉

    ChrisM



  • 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


Anmelden zum Antworten