1

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

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

2 回答 2

4

QSocketNotifier文档

尽管该类称为 QSocketNotifier,但它通常用于除套接字之外的其他类型的设备。QTcpSocket 和 QUdpSocket 通过信号提供通知,因此通常不需要在它们上使用 QSocketNotifier。

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

于 2012-07-12T12:50:31.857 回答
1

我在使用 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();
}
于 2013-11-18T02:03:30.810 回答