Qt文档阅读笔记-Threaded Fortune Server Example解析

x33g5p2x  于2021-11-10 转载在 其他  
字(2.2k)|赞(0)|评价(0)|浏览(418)

Fortune服务端展示了如何去创建一个多线程服务端。此实例与Fortune客户端运行。

首先继承QTcpServer重写下子类,方便实现多线程。

这里需要两个类:一个是QTcpServer的子类,一个是QThread的子类

class FortuneServer : public QTcpServer
  {
      Q_OBJECT

  public:
      FortuneServer(QObject *parent = 0);

  protected:
      void incomingConnection(qintptr socketDescriptor) override;

  private:
      QStringList fortunes;
  };

重写了QTcpServer的QTcpServer::incomingConnection(),使用list存储服务端需要返回的字符串:

FortuneServer::FortuneServer(QObject *parent)
      : QTcpServer(parent)
  {
      fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
               << tr("You've got to think about tomorrow.")
               << tr("You will be surprised by a loud noise.")
               << tr("You will feel hungry again in another hour.")
               << tr("You might have mail.")
               << tr("You cannot kill time without injuring eternity.")
               << tr("Computers are not intelligent. They only think they are.");
  }

QTcpServer::incomingConnection()中有个socketDescriptor参数,表示元素套接字描述符。这里FortuneThread有3个参数,一个是套接字描述符,一个是发送给客户端的字符串,还有个是传入的指向父节点的指针,并且关联了信号和槽,当线程完成后现在会被指定释放,使用start()运行。

void FortuneServer::incomingConnection(qintptr socketDescriptor)
  {
      QString fortune = fortunes.at(QRandomGenerator::global()->bounded(fortunes.size()));
      FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
      connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
      thread->start();
  }

FortuneThread继承了QThread,重写了run方法,业务功能是操作被对应的socket。并且有个错误信号:

class FortuneThread : public QThread
  {
      Q_OBJECT

  public:
      FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent);

      void run() override;

  signals:
      void error(QTcpSocket::SocketError socketError);

  private:
      int socketDescriptor;
      QString text;
  };

Fortune构造函数:

FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject *parent)
      : QThread(parent), socketDescriptor(socketDescriptor), text(fortune)
  {
  }

下面是run方法,首先创建一个QTcpSocket,然后设置socketDescriptor,用于操作本地套接字。

void FortuneThread::run()
  {
      QTcpSocket tcpSocket;
      
      if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
          emit error(tcpSocket.error());
          return;
      }

随后构造数据:

QByteArray block;
      QDataStream out(&block, QIODevice::WriteOnly);
      out.setVersion(QDataStream::Qt_4_0);
      out << text;

最后进行TCP的分手:

tcpSocket.write(block);
      tcpSocket.disconnectFromHost();
      tcpSocket.waitForDisconnected();
  }

相关文章