チャット
ユーザーアプリケーションで Qt GRPC クライアント API を使用します。
Chat では、チャットユーザーを認証し、チャットクライアント間でショートメッセージを送受信する方法を説明します。このアプリケーションは以下のメッセージ形式をサポートしています:
- テキスト - メッセージ入力フィールドを使用してメッセージを送信します。
- 画像 - 画像バッファをクリップボードにコピーし、
'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-name
とuser-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サーバストリーミングへのサブスクリプションを使用してサーバとの通信を開始します:
auto stream = m_client->messageList(qtgrpc::examples::chat::None()); auto streamPtr = stream.get(); auto finishedConnection = std::make_shared<QMetaObject::Connection>(); *finishedConnection = QObject::connect(streamPtr, &QGrpcServerStream::finished, this, [this, finishedConnection, stream = std::move(stream)](const QGrpcStatus &status) { if (!status.isOk()) { qCritical() << "Stream error(" << status.code() << "):" << status.message(); } if (status.code() == QtGrpc::StatusCode::Unauthenticated) { emit authFailed(); } else if (status.code() != QtGrpc::StatusCode::Ok) { emit networkError(status.message()); setState(Disconnected); } else { setState(Disconnected); } disconnect(*finishedConnection); }); QObject::connect(streamPtr, &QGrpcServerStream::messageReceived, this, [this, name, password, stream = streamPtr]() { if (m_userName != name) { m_userName = name; m_password = password; emit userNameChanged(); } setState(Connected); if (const auto msg = stream->read<qtgrpc::examples::chat::ChatMessages>()) m_messages.append(msg->messages()); });
QGrpcServerStream ハンドラは、クライアントアプリケーションが接続すべきシグナルを提供します。
QGrpcServerStream::finished シグナルを使用して、エラーとストリームの正常終了の両方を処理します。ステータスコードは、ストリーム通信中に発生したエラーを示します。
サーバーがストリームに新しいメッセージを送信すると、QGrpcServerStream はQGrpcServerStream::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); // We explicitly take a copy of the reply pointer, since moving it into // the lambda would make the get() function invalid. // Reply's lifetime will be extended until finished() is emitted. // Qt::SingleShotConnection is needed to destroy the lambda (and its capture). auto *replyPtr = reply.get(); connect( replyPtr, &QGrpcCallReply::finished, this, [reply = std::move(reply)](const QGrpcStatus &status) { if (!status.isOk()) qDebug() << "Failed to send message: " << status; }, Qt::SingleShotConnection);
次に、gRPC サーバはクライアント・メッセージを処理し、SimpleChat/messageList
ストリームを通じて、接続されているすべてのクライアントにブロードキャストします。
注意: この例では、サーバ実装にリファレンス gRPC C++ API を使用しています。
©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。