4 Stimmen

Wie kann ich einzelne Tastenanschläge in einer Unix-Konsolenanwendung ohne Blockierung erfassen?

Ich habe einen sehr einfachen TCP-Server in C geschrieben. Er läuft unendlich lange und wartet auf Verbindungen. Unter Windows verwende ich select um zu prüfen, ob der Socket aktiv ist, und wenn das nicht der Fall ist, habe ich den folgenden Code, der es mir ermöglicht, das Programm durch Drücken von 'q' auf der Tastatur zu beenden:

if( kbhit() ) {
   char c = getch();
   if( c == 'q' ) break;
}

Dies funktioniert nicht unter Unix, da kbhit gibt es nicht und getch funktioniert anders. Ich habe einige Beispielcode die die tcsetattr um die Terminaleinstellungen zu ändern und eine zeichenweise Eingabe zu ermöglichen. Nach dem Aufruf der init-Funktion öffne ich /dev/stdin (mit O_NONBLOCK ) und ein Zeichen lesen, aber read( f, &c, 1 ) blockiert, bis eine Figur getroffen wird.

Ich könnte wohl einen separaten Thread eröffnen und es auf unbestimmte Zeit warten und dann den ersten Thread signalisieren, wenn der Benutzer "q" drückt, aber das scheint ein wenig schwerfällig zu sein. Sicherlich gibt es einen einfacheren Weg?

5voto

Lou Franco Punkte 85315

Fügen Sie stdin zu Ihrer Liste der Select-Handles hinzu, und wenn es Daten enthält, rufen Sie read auf, um ein Zeichen daraus zu lesen.

1voto

Fügen Sie stattdessen "f" aus Ihrem

read( f, &c, 1 )

um einen Anruf auszuwählen. Wenn f zum Lesen bereit ist, wurde ein Zeichen gedrückt, und read() wird nicht blockiert.

1voto

mpez0 Punkte 2689

Unter Unix, ob auf der Systemkonsole oder in einem X-Terminal-Fenster, läuft die Tastatureingabe über ein virtuelles Terminal. Das Gerät /dev/tty ist heutzutage der übliche Weg, um auf das Kontrollterminal eines Prozesses zuzugreifen. Andere Gerätemanipulationen als Öffnen/Schließen/Lesen/Schreiben werden alle durch den ioctl(2)-Systemaufruf für dieses spezifische Gerät abgewickelt. Die allgemeine Vorstellung von dem, was Sie tun wollen, ist

Öffnen Sie das steuernde Terminal (das stdin sein kann oder auch nicht)

Ändern Sie den Betriebsmodus dieses Terminals so, dass es zurückkehrt, ohne auf eine vollständige Eingabezeile zu warten (dies ist der normale Standard).

Fahren Sie mit dem Rest Ihres Programms fort, wohl wissend, dass Lesevorgänge von diesem Terminal (das stdin sein könnte) Teilzeilen oder sogar null Zeichen zurückgeben können, ohne dass dies ein Fehler oder eine Abbruchbedingung ist.


Eine ausführliche Antwort auf die Frage, wie der zweite Schritt auszuführen ist, finden Sie unter FAQ zur C-Programmierung . Sie weisen auch darauf hin, dass dies eine Frage des Betriebssystems und nicht der Sprache ist. Sie bieten neun Möglichkeiten an, aber die drei wichtigsten, die für diese Frage relevant sind, sind

  1. Verwenden Sie die curses(3)-Bibliothek
  2. Alte BSD-Systeme verwenden sgttyb, um CBREAK oder RAW zu setzen
  3. Posix- oder alte System-V-Systeme verwenden TCGETAW/TCSETAW, um c_cc[VMIN] auf 1 und c_cc[VTIME] auf 0 zu setzen.

Einige Hinweise in den C-FAQ können zu folgenden Punkten führen diese Seite der kbhit-Codefragmente .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X