チャット

ユーザーアプリケーションでQt GRPC クライアント API を使用する。

チャットは、チャットユーザーを認証し、チャットクライアント間でショートメッセージを送受信する方法を説明します。このアプリケーションは以下のメッセージ形式をサポートしています:

  • テキスト - メッセージ入力フィールドを使用してメッセージを送信します。
  • 画像 - 画像バッファをクリップボードにコピーし、'Ctrl + V' ショートカットを使用してメッセージを送信します。

チャットクライアントはprotobufスキームで記述されたシンプルなRPCプロトコルを使用します:

package qtgrpc.examples.chat;

message ChatMessage {
    enum ContentType {
        Unknown = 0;
        Text = 1;
        Image = 2;
    };
    uint64 timestamp = 1;
    bytes content = 2;
    ContentType type = 3;
    string from = 4;
}

message ChatMessages {
    repeated ChatMessage messages = 1;
}

message User {
    string name = 1;
    string password = 2;
}

message Users {
    repeated User users = 1;
}

message None {}

service SimpleChat {
    rpc messageList(None) returns (stream ChatMessages) {}
    rpc sendMessage(ChatMessage) returns (None) {}
}

ログイン画面で、ユーザー認証情報を入力します:

注意: ユーザーのリストはサーバー側であらかじめ定義されており、一定です。すべてのユーザーのパスワードはqwerty です。

チャットクライアントは、user-nameuser-password HTTPヘッダーを使用してサーバーを認証します。これらのフィールドはメタデータ内に設定される。各 gRPCメッセージはメッセージヘッダにユーザー認証情報を含みます。メタデータはQGrpcChannelOptions 内のQGrpcHttp2Channel に一度渡され、暗黙のうちに再利用される:

QGrpcChannelOptions channelOptions;
QHash<QByteArray, QByteArray> metadata = {
    { "user-name", { name.toUtf8() } },
    { "user-password", { password.toUtf8() } },
};
channelOptions.setMetadata(metadata);
std::shared_ptr<QAbstractGrpcChannel>
    channel = std::make_shared<QGrpcHttp2Channel>(url, channelOptions);

チャットクライアントは、gRPC サーバーストリーミングへのサブスクリプションを使用してサーバーとの通信を開始する:

autostream=  m_client->messageList(qtgrpc::examples::chat::None());autostreamPtr=stream.get();autofinishedConnection=std::make_shared<QMetaObject::Connection>();*finishedConnection =QObject::connect(streamPtr, &)QGrpcServerStream::finished, this, [this,finishedConnection,stream=std::move(stream)](constQGrpcStatus(&status) {if(!status.isOk()) { { { { { { { (!status.isOk()))                                               qCritical() << "Stream error(" << status.code()
                                                          << "):"<<status.message(); }if(status.code()==) QtGrpc::StatusCode::Unauthenticated) {emitauthFailed(); }else if(status.code()!= QtGrpc::StatusCode::Ok) {networkError(status.message()); setState(Disconnected); }else{ setState(Disconnected); } disconnect(*finishedConnection); });QObject::connect(streamPtr, &)QGrpcServerStream::messageReceived, this, [this,name,password,stream=streamPtr]() {if(m_userNamem_userName! =name) { m_userName=name; m_password=password;emituserNameChanged(); } setState(Connected);if(const automsg=  stream->read<qtgrpc::examples::chat::ChatMessages>()) m_messages.append(msg->messages()); });

QGrpcServerStream ハンドラは、クライアント・アプリケーションが接続すべきシグナルを提供します。

エラーとストリームの正常終了の両方を処理するには、QGrpcServerStream::finished シグナルを使用します。ステータス・コードは、ストリーム通信中に発生したエラーを示します。

サーバーがストリームに新しいメッセージを送信すると、QGrpcServerStreamQGrpcServerStream::messageReceived シグナルを発信します。このシグナルに接続されたスロットは、チャットメッセージを処理します。SimpleChat/messageList サーバーストリームから受信したメッセージは、カスタムQAbstractListModel モデルに収集され、ユーザーに表示されます。

QGrpcServerStream::finished シグナルが発信されると、このストリームインスタンスでできることはなくなりますので、新しいサブスクリプションを開始する必要があります。

購読が成功すると、チャットクライアントは会話画面に切り替わり、ショートメッセージを見たり送ったりできるようになります:

メッセージを送信するには、単項 RPC 呼び出しSimpleChat/sendMessage を使用します。メッセージを送信するには、単項 RPC 呼び出しChatMessage を使用します。クライアント・アプリケーションは、まず protobuf メッセージのフィールドを設定し、次にクライアント・メソッドを呼び出します:

qtgrpc::examples::chat::ChatMessage msg; msg.setContent(content.toUtf8()); msg.setType(qtgrpc::examples::chat::ChatMessage::ContentType::Text); msg.setTimestamp(QDateTime::currentMSecsSinceEpoch()); msg.setFrom(m_userName); std::unique_ptr<QGrpcCallReply> reply=  m_client->sendMessage(msg);// replyポインタをラムダ内に移動するとget()関数が無効になってしまうため、 // replyポインタのコピーを明示的に取得します。// replyの有効期限はfinished()が発行されるまで延長されます。// ラムダ(とそのキャプチャ)を破棄するにはQt::SingleShotConnectionが必要です。QGrpcCallReply::finished, this,[reply =std::move(reply)](constQGrpcStatus&status) {if(!status.isOk())            qDebug() << "Failed to send message: " << status;
   },  Qt::SingleShotConnection);

次に、gRPC サーバーはクライアント・メッセージを処理し、SimpleChat/messageList ストリームを通じて、接続しているすべてのクライアントにブロードキャストする。

注: この例では、サーバーの実装にgRPC C++ API を使用しています。

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

© 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.