フォーチュン・サーバー

ネットワーク サービス用のサーバーを作成する方法を示します。

この例は、Fortune Client例またはBlocking Fortune Client例と並行して実行することを意図している。

Screenshot of the Fortune Server example

QTcpServer を使用して着信TCP接続を受け付け、単純なQDataStream ベースのデータ転送プロトコルを使用して、(Fortune Clientの例から)接続中のクライアントにフォーチュンを書き込んでから接続を閉じます。

class Server : public QDialog
{
    Q_OBJECT

public:
    explicit Server(QWidget *parent = nullptr);

private slots:
    void sendFortune();

private:
    void initServer();

    QLabel *statusLabel = nullptr;
    QTcpServer *tcpServer = nullptr;
    QList<QString> fortunes;
};

サーバーは、着信接続を処理するために、1つのスロットを持つ単純なクラスを使用して実装されています。

    tcpServer = new QTcpServer(this);
    if (!tcpServer->listen()) {
        QMessageBox::critical(this, tr("Fortune Server"),
                              tr("Unable to start the server: %1.")
                              .arg(tcpServer->errorString()));
        close();
        return;
    }
    QString ipAddress;
    const QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    // use the first non-localhost IPv4 address
    for (const QHostAddress &entry : ipAddressesList) {
        if (entry != QHostAddress::LocalHost && entry.toIPv4Address()) {
            ipAddress = entry.toString();
            break;
        }
    }
    // if we did not find one, use IPv4 localhost
    if (ipAddress.isEmpty())
        ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
    statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n"
                            "Run the Fortune Client example now.")
                         .arg(ipAddress).arg(tcpServer->serverPort()));

コンストラクタで、ServerオブジェクトはQTcpServer::listen ()を呼び出し、任意のポートですべてのアドレスをリッスンするQTcpServer 。そして、フォーチュン・クライアントがどのポートに接続すべきかがユーザーに分かるように、QTcpServer で選んだポートをラベルに表示する。

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.");

私たちのサーバーは、接続中のクライアントに送信できるランダムな運勢のリストを生成する。

connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune);

クライアントが私たちのサーバーに接続すると、QTcpServerQTcpServer::newConnection() を発行する。その結果、sendFortune()スロットが呼び出される:

void Server::sendFortune()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_6_5);

    out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())];

このスロットの目的は、おみくじのリストからランダムな行を選択し、QDataStream を使ってQByteArray にエンコードし、接続ソケットに書き込むことである。これはQTcpSocket を使ってバイナリデータを転送する一般的な方法である。まず、QByteArrayQDataStream オブジェクトを作成し、QDataStream のコンストラクタにバイト配列を渡す。次に、QDataStream のプロトコルのバージョンをQDataStream::Qt_5_10 に設定し、将来のバージョンの Qt のクライアントと通信できるようにします(QDataStream::setVersion() を参照)。続けて、ランダム・フォーチュンをストリーミングする。

    QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
    connect(clientConnection, &QAbstractSocket::disconnected,
            clientConnection, &QObject::deleteLater);

次にQTcpServer::nextPendingConnection() を呼び出し、接続のサーバー側を表すQTcpSocket を返します。QTcpSocket::disconnected() をQObject::deleteLater() に接続することで、切断後にソケットが削除されるようにしている。

    clientConnection->write(block);
    clientConnection->disconnectFromHost();
}

エンコードされたおみくじはQTcpSocket::write ()を使って書き込まれ、最後にQTcpSocket::disconnectFromHost ()を呼び出す。 ()は、QTcpSocket がネットワークへのおみくじの書き込みを終了した後に接続を閉じる。QTcpSocket は非同期で動作するため、この関数が戻った後にデータが書き込まれ、制御はQtのイベントループに戻る。その後、ソケットが閉じられ、QObject::deleteLater() がソケットを削除する。

プロジェクト例 @ code.qt.io

Fortune Clientと Threaded Fortune Serverも参照してください

©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundationによって発行されたGNU Free Documentation License version 1.3の条項に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。