スレッド化されたFortuneサーバー
「スレッド化されたFortuneサーバー」のサンプルでは、スレッドを使用して異なるクライアントからのリクエストを処理する、シンプルなネットワークサービス用のサーバーを作成する方法を示しています。このサンプルは、「Fortuneクライアント」のサンプルと併せて実行することを想定しています。

この例の実施方法は「Fortune Server」の例と似ていますが、ここでは各接続を別々のスレッドで開始するQTcpServer のサブクラスを実装します。
これには、QTcpServer のサブクラスであるFortuneServerと、QThread を継承するFortuneThreadという2つのクラスが必要です。
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(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;FortuneServerの例と同様に、QDataStream を使用して、フォーチュンをQByteArray に変換します。
tcpSocket.write(block);
tcpSocket.disconnectFromHost();
tcpSocket.waitForDisconnected();
}しかし、前の例とは異なり、最後に `QTcpSocket::waitForDisconnected()` を呼び出して処理を終了します。これにより、ソケットの接続が切断されるまで呼び出し元スレッドはブロックされます。別のスレッドで実行しているため、GUIは応答性を維持します。
「Fortuneサーバー」、「Fortuneクライアント」、および「ブロッキングFortuneクライアント」も参照してください 。
© 2026 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.