【问题标题】:qsocketnotifier fires activated signal continuously even when there is 0 data on socket即使套接字上的数据为 0,qsocketnotifier 也会连续触发激活信号
【发布时间】:2012-07-12 00:04:42
【问题描述】:

我正在尝试将 qsocketnotifier 与 TCP 套接字一起使用,问题是即使套接字上没有要读取的数据,qsocketnotifier 也会持续触发“激活”信号。我已经在“阻塞”和“非阻塞”模式下在套接字上尝试过这个。行为是一样的。有没有人看到过这个? 我正在粘贴下面的代码。

 QSocketNotifier *notifier = new QSocketNotifier(gwSocketId, QSocketNotifier::Read, this);
    connect(notifier, SIGNAL(activated(int)), this, SLOT(processClientEvents()));

【问题讨论】:

    标签: qt qt4.7 qt5


    【解决方案1】:

    来自QSocketNotifier docs

    虽然该类被称为 QSocketNotifier,但它通常用于 插座以外的其他类型的设备。 QTcpSocket 和 QUdpSocket 提供 通过信号通知,因此通常不需要使用 QSocketNotifier 在他们身上。

    QTcpSocket 继承自 QIODevice,因此具有信号 readyRead()。我认为这个信号就是你所追求的。

    【讨论】:

      【解决方案2】:

      我在使用 QSocketNotifier + QTextStream 从标准输入读取时遇到了同样的问题。如果通过一次写入将多行发送到应用程序,我将获得比要读取的行更多的 QSocketNotifier::activated() 信号。导致一个额外的 QTextStream::readLine() 调用会阻塞,导致我的应用程序中的事件处理停止,直到我发送另一行。

      我尝试使用 QTextStream::readAll 但它总是阻塞直到文件结束,这使得问题出现在第一个 QSocketNotifier::activated() 信号上。

      在试图弄清楚如何判断在进入阻塞 QTextStream::readLine() 调用之前是否实际上有任何数据要从标准输入读取之后,我终于停止使用 QTextStream 并使用 fgets()反而。这似乎解决了我的问题。

      这里有一些示例代码(不适合处理非常大的行,这是给读者的练习)。希望这可以避免我在试图解决这个问题时遇到的麻烦。我已经进行了一些额外的信号/事件处理,因为这是确定您是否进入阻塞状态的可靠方法。

      示例 StdinReader 标头:

      #include <QCoreApplication>
      #include <QSocketNotifier>
      #include <QTimer>
      #include <cstdio>
      
      class StdinReader : public QObject
      {
        Q_OBJECT
      
      public:
        StdinReader(QObject* parent = 0)
          : QObject(parent),
            notifier(new QSocketNotifier(fileno(stdin), QSocketNotifier::Read, this))
        {
          connect(this, SIGNAL(sigOutputData(QString)), SLOT(outputData(QString)));
          connect(notifier, SIGNAL(activated(int)), SLOT(consumeData()));
          notifier->setEnabled(true);
          QTimer::singleShot(1000, this, SLOT(timerTick()));
        }
      
        ~StdinReader() { }
      
      signals:
        void sigOutputData(QString);
      
      private slots:
        void outputData(QString data)
        {
          fprintf(stdout, "Data: %s\n", data.trimmed().toUtf8().constData());
          fflush(stdout);
        }
      
        void timerTick()
        {
          emit sigOutputData(QString::fromUtf8("tick"));
          QTimer::singleShot(1000, this, SLOT(timerTick()));
        }
      
        void consumeData()
        {
          notifier->setEnabled(false);
      
          fprintf(stdout, "Reading\n");
          fflush(stdout);
      
          char sbuf[8192];
          if (!fgets(sbuf, sizeof(sbuf), stdin)) {
            fprintf(stdout, "EOF\n");
            fflush(stdout);
            QCoreApplication::exit();
            return;
          }
      
          emit sigOutputData(QString::fromUtf8(sbuf));
      
          notifier->setEnabled(true);
        }
      
      private:
        QSocketNotifier* notifier;
      };
      

      示例 main()

      int main(int argc, char *argv[])
      {
        QCoreApplication a(argc, argv);
        new StdinReader(&a);
        return a.exec();
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-29
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 2021-09-19
        • 1970-01-01
        • 1970-01-01
        • 2011-06-02
        • 1970-01-01
        相关资源
        最近更新 更多