Wie kann ich, ohne zu blockieren einzelne Tastenanschläge in einer Unix-Konsole App erfassen?
Frage
Ich habe einen sehr einfacher TCP-Server in C. geschrieben auf unbestimmte Zeit läuft, für Verbindungen zu warten. Unter Windows verwende ich select
für die Aktivität auf dem Sockel zu überprüfen, und wenn es nicht ist, ich habe den folgenden Code mich durch Schlagen ‚q‘ auf der Tastatur zu beenden zuzulassen:
if( kbhit() ) {
char c = getch();
if( c == 'q' ) break;
}
Das funktioniert nicht auf Unix, da kbhit
nicht existiert und getch
funktioniert anders. Ich fand einige Beispielcode dass Terminaleinstellungen verwendet tcsetattr
und Eingabe ermöglichen Zeichen-für-Zeichen zu ändern. Nach der init-Funktion aufrufen, ich öffne / dev / stdin (mit O_NONBLOCK
) und ein Zeichen lesen, aber read( f, &c, 1 )
blockiert, bis ein Charakter getroffen wird.
Ich glaube, ich könnte einen separaten Thread laichen und habe es auf unbestimmte Zeit warten, und dann wird das Signal den ersten Thread, wenn die ‚q‘ Benutzer-Hits, aber das ist ein wenig plump erscheint. Sicherlich gibt es einen einfacheren Weg?
Lösung
Fügen Sie stdin in die Liste der Auswahlgriffe, und wenn es Daten hat, lesen Sie rufen ein Zeichen von ihm zu lesen.
Andere Tipps
Rather, fügen Sie "f" von Ihrem
read( f, &c, 1 )
Anruf auszuwählen. Wenn f bereit für Lese ist, hat ein Zeichen gedrückt wurde, und lesen () nicht blockieren.
In Unix, ob auf der Systemkonsole oder in einem X-Terminal-Fenster, Tastatur I / O geht durch ein virtuelles Terminal. Gerät / dev / tty ist die übliche Art und Weise, in diesen Tagen, eines Prozesses, der Steuerdatenstation zugreift. Vorrichtung Manipulationen andere als Öffnen / Schließen / Lesen / Schreiben sind alle von der ioctl behandelt (2) Systemaufruf für dieses spezielle Gerät. Die allgemeine Vorstellung von dem, was Sie tun möchten, ist
Öffnen Sie den Steueranschluss (das kann oder nicht sein stdin)
ändern Sie den Betriebsmodus auf diesem Terminal zurück, ohne für eine volle Linie des Eingangs zu warten (was die normale Standardeinstellung)
mit dem Rest des Programms weiter, wohl wissend, dass von diesem Terminal liest (was könnte stdin) zurückkehren Teillinien oder sogar Null-Zeichen ohne es Bedingung eines Fehlers oder eine Kündigung zu sein.
Eine detaillierte Antwort auf wie der zweite Schritt zu tun ist an der C-Programmierung FAQ . Sie weisen darauf hin, dass dies eine O Frage, keine Sprache Frage. Sie bieten neun Möglichkeiten, aber die drei wichtigsten sind relevant zu dieser Frage sind
- Verwenden Sie die Flüche (3) Bibliothek
- Old BSD-Systeme, Verwendung sgttyb einstellen cbreak oder RAW
- Posix oder alte V-Stil Systeme System verwenden TCGETAW / TCSETAW einstellen c_cc [VMIN] auf 1 und c_cc [VTIME] auf 0.
ein paar Referenzen in der C-FAQ Nach könnte dazu führen, dieser Seite des kbhit Codefragmente .