2009-08-13 15 views
7

Utilizando Qt, intento leer el contenido de la secuencia stdin de forma no bloqueante. Estoy usando el QSocketNotifier para alertarme cuando el socket ha recibido algunos datos nuevos. La configuración para el notificador se ve así:utilizando QTextStream para leer stdin de forma no bloqueada

QSocketNotifier *pNot = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this); 
connect(pNot, SIGNAL(activated(int)), this, SLOT(onData())); 
pNot->setEnabled(true); 

la ranura onData() se parece a esto:

void CIPCListener::onData() 
{ 
    qDebug() << Q_FUNC_INFO; 
    QTextStream stream(stdin, QIODevice::ReadOnly); 

    QString str; 

    forever 
    { 
     fd_set stdinfd; 
     FD_ZERO(&stdinfd); 
     FD_SET(STDIN_FILENO, &stdinfd); 
     struct timeval tv; 
     tv.tv_sec = 0; 
     tv.tv_usec = 0; 
     int ready = select(1, &stdinfd, NULL, NULL, &tv); 
     if(ready > 0) 
     { 
      str += stream.readLine(); 
     } 
     else 
     { 
      break; 
     } 
    } 

    qDebug() << "Recieved data:" << str; 
} 

Como se puede ver que estoy tratando de utilizar la llamada al sistema select() para decirme cuándo Me he quedado sin datos para leer. Sin embargo, en la práctica, lo que está sucediendo es que la llamada select() devuelve 0 después de leer la primera línea de texto. Entonces, por ejemplo, si escribo 5 líneas de texto en la secuencia stdin del proceso, solo leo la primera línea.

¿Cuál podría ser el problema?

+0

¿Has probado readAll en lugar de readLine? – Bob

+0

yup. Creo que usa atEnd() internamente para detectar cuándo se llegó al final de la transmisión. El resultado es que bloquea para siempre. – Thomi

+1

bien, solo otra cosa que puedo pensar es intentar eliminar la implementación actual (la llamada de selección) y hacer algo similar a lo que hace el asistente, ver herramientas \ asistente \ herramientas \ asistente \ control remoto * – Bob

Respuesta

4

Buffer de línea.

El valor predeterminado es el lavado después de "\ n". Si escribe 5 líneas en su proceso, su ranura se llama 5 veces. Si desea evitar eso, debe llamar a setbuf (stdin, _IOFBF). Pero incluso entonces no está garantizado que pueda leer arbitrariamente grandes cantidades de datos en un solo bloque.

Editar: Probablemente sería mejor usar QTextStream :: atEnd() en lugar de seleccionar, ya que QTextStream tiene sus propios búferes internos.

+1

No se puede usar QTextStream :: atEnd() en stdin; la documentación de Qt lo dice (consulte la documentación detallada de la clase). Ver: http://doc.trolltech.com/4.5/qtextstream.html#details – Thomi

1

que he encontrado y el ejemplo de otra respuesta que se adapta a casi a esta pregunta y con el código completo y sencillo:

https://stackoverflow.com/a/7389622/721929

lo he usado para implementar una aplicación basada en consola de QT con un texto menú para elegir en la selección del usuario.

Cuestiones relacionadas