Comment capturer des frappes uniques dans une application de console Unix sans bloquer?

StackOverflow https://stackoverflow.com/questions/184108

  •  06-07-2019
  •  | 
  •  

Question

J'ai un serveur TCP très simple écrit en C. Il fonctionne indéfiniment, dans l'attente des connexions. Sous Windows, j’utilise select pour vérifier l’activité du socket. S’il n’en existe pas, j’ai le code suivant pour me permettre de quitter en appuyant sur la touche 'q' du clavier:

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

Cela ne fonctionne pas sous unix, car kbhit n'existe pas et getch fonctionne différemment. J'ai trouvé un exemple de code qui utilise tcsetattr pour modifier les paramètres du terminal et permettre la saisie caractère par caractère. Après avoir appelé la fonction init, j'ouvre / dev / stdin (avec O_NONBLOCK ) et lis un caractère, mais read (f, & amp; c, 1) bloque jusqu'à ce qu'un caractère est touché.

Je suppose que je pourrais créer un thread distinct et le faire attendre , attendre indéfiniment, puis signaler le premier thread si l'utilisateur appuie sur "q", mais cela semble un peu lourd. Il y a sûrement un moyen plus facile?

Était-ce utile?

La solution

Ajoutez stdin à votre liste de poignées de sélection et, s'il contient des données, appelez read pour en lire un caractère.

Autres conseils

Ajoutez plutôt "& f;" de votre

read( f, &c, 1 )

pour sélectionner un appel. Lorsque f est prêt à être lu, un caractère a été pressé et read () ne bloquera pas.

Sous Unix, que ce soit sur la console système ou dans une fenêtre de terminal X, les E / S du clavier passent par un terminal virtuel. Device / dev / tty est le moyen habituel, ces jours-ci, d'accéder au terminal de contrôle d'un processus. Les manipulations de périphérique autres qu'ouvrir / fermer / lire / écrire sont toutes gérées par l'appel système ioctl (2) de ce périphérique spécifique. L’idée générale de ce que vous voulez faire est

Ouvrez le terminal de contrôle (stdin ou non)

Changez le mode de fonctionnement sur ce terminal pour revenir sans attendre une ligne complète d'entrée (ce qui est la valeur par défaut normale)

Continuez avec le reste de votre programme, sachant que les lectures de ce terminal (qui peuvent être stdin) peuvent renvoyer des lignes partielles ou même zéro caractères sans que cela soit une erreur ou une condition de fin.

La FAQ sur la programmation en C fournit une réponse détaillée sur la deuxième étape. / a>. Ils soulignent également qu'il s'agit d'une question de système d'exploitation, pas d'une question de langue. Ils offrent neuf possibilités, mais les trois principales en rapport avec cette question sont

  1. Utiliser la bibliothèque curses (3)
  2. Anciens systèmes de style BSD, utilisez sgttyb pour définir CBREAK ou RAW
  3. Systèmes de style Posix ou anciens de type System V, utilisez TCGETAW / TCSETAW pour définir c_cc [VMIN] sur 1 et c_cc [VTIME] sur 0.

Après quelques références dans la FAQ C, cela pourrait conduire à cette page de fragments de code kbhit .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top