【问题标题】:using QTextStream to read stdin in a non-blocking fashion使用 QTextStream 以非阻塞方式读取标准输入
【发布时间】:2010-11-19 07:08:26
【问题描述】:

使用 Qt,我试图以非阻塞方式读取标准输入流的内容。当套接字收到一些新数据时,我正在使用 QSocketNotifier 来提醒我。通知程序的设置如下所示:

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

onData() 插槽如下所示:

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;
}

如您所见,我正在尝试使用 select() 系统调用来告诉我何时读取的数据已用完。然而,实际上发生的事情是在我阅读了第一行文本后,select() 调用返回 0。因此,例如,如果我将 5 行文本写入进程的标准输入流,我只会读取第一行。

可能是什么问题?

【问题讨论】:

  • 你试过用 readAll 代替 readLine 吗?
  • 是的。我认为它在内部使用 atEnd() 来检测何时到达流的末尾。结果是它永远阻塞。
  • 好的,我能想到的唯一另一件事是放弃当前的实现(选择调用)并做一些类似于助手所做的事情,请参阅工具\助手\工具\助手\远程控制*
  • 当我直接输入终端时,这段代码运行良好。这对我来说已经足够了......谢谢。 ;)

标签: c++ qt stdin blocking


【解决方案1】:

行缓冲。

默认是在“\n”之后刷新。如果您在进程中写入 5 行,您的插槽将被调用 5 次。如果你想避免这种情况,你必须调用 setbuf(stdin, _IOFBF)。但即便如此,也不能保证你可以在一个块中读取任意大量的数据。

编辑:最好使用 QTextStream::atEnd() 而不是 select,因为 QTextStream 有自己的内部缓冲区。

【讨论】:

【解决方案2】:

我在其他答案中找到了几乎适合这个问题的示例,并且代码完整而简单:

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

我已经用它来实现一个基于 QT 控制台的应用程序,该应用程序带有一个文本菜单供用户选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 2016-07-28
    • 2017-12-12
    • 2013-09-03
    相关资源
    最近更新 更多