Chat

Verwendung der Qt GRPC Client-API in den Benutzeranwendungen.

Chat erklärt, wie man Chat-Benutzer authentifiziert und Kurznachrichten zwischen Chat-Clients sendet und empfängt. Die Anwendung unterstützt die folgenden Nachrichtenformate:

  • Text - Verwenden Sie das Nachrichteneingabefeld, um die Nachricht zu senden.
  • Bild - Kopieren Sie den Bildpuffer in die Zwischenablage, um die Nachricht über die Verknüpfung 'Ctrl + V' zu senden.

Der Chat-Client verwendet ein einfaches RPC-Protokoll, das im Protobuf-Schema beschrieben ist:

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) {}
}

Geben Sie auf dem Anmeldebildschirm die Anmeldedaten des Benutzers ein:

Hinweis: Die Liste der Benutzer wird serverseitig vordefiniert und ist konstant. Das Passwort für alle Benutzer lautet qwerty.

Der Chat-Client authentifiziert sich beim Server über die HTTP-Header user-name und user-password. Diese Felder werden in den Metadaten festgelegt. Jede gRPC Nachricht enthält die Anmeldedaten des Benutzers im Nachrichtenkopf. Die Metadaten werden einmal an QGrpcHttp2Channel innerhalb von QGrpcChannelOptions übergeben und implizit wiederverwendet:

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

Der Chat-Client beginnt die Kommunikation mit dem Server über ein Abonnement des gRPC Serverstreaming:

auto stream =  m_client->messageList(qtgrpc::examples::chat::None());auto streamPtr = stream.get();auto finishedConnection = std::make_shared<QMetaObject::Verbindung>();*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()); });

Der QGrpcServerStream Handler liefert die Signale, mit denen sich die Client-Anwendung verbinden soll.

Verwenden Sie das Signal QGrpcServerStream::finished, um sowohl Fehler als auch die erfolgreiche Beendigung des Streams zu behandeln. Der Statuscode gibt den Fehler an, der während der Stream-Kommunikation aufgetreten ist.

Wenn der Server neue Nachrichten an den Stream sendet, sendet QGrpcServerStream das Signal QGrpcServerStream::messageReceived. Der mit diesem Signal verbundene Slot verarbeitet die Chatnachricht. Nachrichten, die vom SimpleChat/messageList Server-Stream empfangen werden, werden im benutzerdefinierten QAbstractListModel Modell gesammelt und dem Benutzer angezeigt.

Wenn das Signal QGrpcServerStream::finished ausgesendet wird, können Sie mit dieser Stream-Instanz nichts mehr tun, so dass Sie ein neues Abonnement initiieren müssen.

Nach erfolgreicher Subskription schaltet der Chat-Client auf den Konversationsbildschirm um und ermöglicht es Ihnen, Kurznachrichten zu sehen und zu senden:

Um die Nachricht zu senden, verwenden Sie einen unären RPC-Aufruf SimpleChat/sendMessage. Die Client-Anwendung setzt zunächst die Felder der ChatMessage protobuf-Nachricht und ruft dann die Client-Methode auf:

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);// Wir nehmen explizit eine Kopie des Reply-Zeigers, da das Verschieben in// das Lambda die get()-Funktion ungültig machen würde.// Die Lebensdauer von Reply wird verlängert, bis finished() ausgegeben wird.// Qt::SingleShotConnection wird benötigt, um das Lambda (und seine Erfassung) zu zerstören.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);

Anschließend verarbeitet der Server gRPC die Client-Nachrichten und sendet sie über den Stream SimpleChat/messageList an alle verbundenen Clients.

Hinweis: Dieses Beispiel verwendet die Referenz gRPC C++ API in der Serverimplementierung.

Beispielprojekt @ 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.