スレッド・フォーチュン・サーバー
Threaded Fortune Serverサンプルは、スレッドを使用して異なるクライアントからの要求を処理する、単純なネットワークサービスのサーバーを作成する方法を示しています。これは、Fortune Clientの例と一緒に実行することを目的としています。
この例の実装は、Fortune Serverの例と似ていますが、ここでは、各接続を異なるスレッドで開始するQTcpServer のサブクラスを実装します。
そのためには2つのクラスが必要です:FortuneServerはQTcpServer のサブクラスで、FortuneThreadはQThread を継承している。
class FortuneServer : public QTcpServer { Q_OBJECT public: FortuneServer(QObject *parent = nullptr); protected: void incomingConnection(qintptr socketDescriptor) override; private: QStringList fortunes; };
FortuneServerはQTcpServer を継承し、QTcpServer::incomingConnection ()を再実装している。FortuneServerは、ランダムな運勢のリストを保存するためにも使用する。
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."); }
FortuneServerのコンストラクタを使用して、単純に運勢のリストを生成する。
void FortuneServer::incomingConnection(qintptr socketDescriptor) { QString fortune = fortunes.at(QRandomGenerator::global()->bounded(fortunes.size())); FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this); connect(thread, &FortuneThread::finished, thread, &FortuneThread::deleteLater); thread->start(); }
QTcpServer::incomingConnection() の実装では、FortuneThread オブジェクトを作成し、FortuneThread のコンストラクタに受信ソケット記述子とランダムな運勢を渡す。FortuneThread の finished() シグナルをQObject::deleteLater() に接続することで、スレッドが終了したら確実に削除されるようにしている。その後、QThread::start ()を呼び出すことで、スレッドを開始することができる。
class FortuneThread : public QThread { Q_OBJECT public: FortuneThread(qintptr socketDescriptor, const QString &fortune, QObject *parent); void run() override; signals: void error(QTcpSocket::SocketError socketError); private: qintptr socketDescriptor; QString text; };
FortuneThread クラスに話を移すと、これはQThread のサブクラスで、接続されたソケットにフォーチュンを書き込むのが仕事である。このクラスはQThread::run() を再インプリメントしており、エラーを報告するためのシグナルを持っている。
FortuneThread::FortuneThread(qintptr socketDescriptor, const QString &fortune, QObject *parent) : QThread(parent), socketDescriptor(socketDescriptor), text(fortune) { }
FortuneThread のコンストラクタは、ソケットディスクリプタとフォーチュンテキストを格納するだけで、後で run() で利用できるようになる。
void FortuneThread::run() { QTcpSocket tcpSocket;
run() 関数が最初に行うことは、スタック上にQTcpSocket オブジェクトを作成することである。注目すべき点は、このオブジェクトをスレッド内で作成していることです。これにより、スレッドのイベントループにソケットが自動的に関連付けられます。これにより、FortuneThread::run()からソケットにアクセスしている間に、Qtがメインスレッドからソケットにイベントを送ろうとすることがなくなります。
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) { emit error(tcpSocket.error()); return; }
ソケットの初期化はQTcpSocket::setSocketDescriptor() を呼び、引数にソケットディスクリプタを渡す。これが成功することを期待するが、念のため(可能性は低いが、システムがリソースを使い果たす可能性がある)、戻り値をキャッチし、エラーがあれば報告する。
QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_6_5); out << text;
フォーチュン・サーバーの例と同様に、QDataStream を使ってフォーチュンをQByteArray にエンコードする。
tcpSocket.write(block); tcpSocket.disconnectFromHost(); tcpSocket.waitForDisconnected(); }
しかし、前の例とは異なり、ソケットが切断されるまで呼び出し元のスレッドをブロックするQTcpSocket::waitForDisconnected()を呼び出して終了する。別スレッドで実行しているので、GUIは応答し続ける。
Fortune Server、Fortune Client、Blocking Fortune Clientも参照のこと 。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.