¿Cómo puedo capturar teclas individuales en una aplicación de consola Unix sin bloquear?

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

  •  06-07-2019
  •  | 
  •  

Pregunta

Tengo un servidor TCP muy simple escrito en C. Se ejecuta indefinidamente, esperando conexiones. En Windows, uso select para verificar la actividad en el zócalo, y si no hay ninguna, tengo el siguiente código que me permite salir presionando 'q' en el teclado:

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

Esto no funciona en Unix, ya que kbhit no existe y getch funciona de manera diferente. Encontré algunos código de muestra usa tcsetattr para cambiar la configuración del terminal y permitir la entrada carácter por carácter. Después de llamar a la función init, abro / dev / stdin (con O_NONBLOCK ) y leo un carácter, pero read (f, & amp; c, 1) bloquea hasta que un carácter es golpeado.

Supongo que podría generar un hilo separado y hacer que lo espere indefinidamente y luego señalar el primer hilo si el usuario toca 'q', pero eso parece un poco pesado. ¿Seguramente hay una manera más fácil?

¿Fue útil?

Solución

Agregue stdin a su lista de identificadores seleccionados, y si tiene datos, llame a read para leer un carácter de él.

Otros consejos

Más bien, agregue " f " de tu

read( f, &c, 1 )

para seleccionar la llamada. Cuando f está listo para leer, se ha presionado un carácter y read () no se bloqueará.

En Unix, ya sea en la consola del sistema o en una ventana de terminal X, la E / S del teclado pasa por un terminal virtual. Device / dev / tty es la forma habitual, en estos días, de acceder al terminal de control de un proceso. Las manipulaciones de dispositivos que no sean abrir / cerrar / leer / escribir son manejadas por la llamada al sistema ioctl (2) para ese dispositivo específico. La idea general de lo que quieres hacer es

Abra el terminal de control (que puede o no ser estándar)

Cambie el modo de funcionamiento en ese terminal para que regrese sin esperar una línea completa de entrada (que es el valor predeterminado normal)

Continúe con el resto de su programa, sabiendo que las lecturas de ese terminal (que pueden ser estándar) pueden devolver líneas parciales o incluso cero caracteres sin que sea una condición de error o terminación.


Una respuesta detallada sobre cómo hacer el segundo paso se encuentra en las preguntas frecuentes sobre programación en C . También señalan que esta es una pregunta del sistema operativo, no una pregunta de idioma. Ofrecen nueve posibilidades, pero las tres principales relevantes para esta pregunta son

  1. Usa la biblioteca curses (3)
  2. Sistemas de estilo BSD antiguos, use sgttyb para configurar CBREAK o RAW
  3. Posix o sistemas de estilo System V anteriores, utilice TCGETAW / TCSETAW para establecer c_cc [VMIN] en 1 y c_cc [VTIME] en 0.

Seguir un par de referencias en las preguntas frecuentes de C podría llevar a esta página de fragmentos de código kbhit .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top