聊天

在用户应用程序中使用 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 头部验证服务器。这些字段由 QGrpcMetadata 设置。每个 gRPC 消息都将用户凭据包含在消息头部。 QGrpcMetadata 一次传递给 QGrpcHttp2Channel 中的 QGrpcChannelOptions 并隐式重用

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

聊天客户端通过订阅 gRPC 服务器流来开始与服务器的通信

auto stream = m_client->streamMessageList(qtgrpc::examples::chat::None());
QObject::connect(stream.get(), &QGrpcServerStream::errorOccurred, this,
                 [this, stream](const QGrpcStatus &status) {
                     qCritical()
                             << "Stream error(" << status.code() << "):" << status.message();
                     if (status.code() == QGrpcStatus::Unauthenticated) {
                         emit authFailed();
                     } else {
                         emit networkError(status.message());
                         setState(Disconnected);
                     }
                 });

QObject::connect(stream.get(), &QGrpcServerStream::finished, this,
                 [this, stream]() { setState(Disconnected); });

QObject::connect(stream.get(), &QGrpcServerStream::messageReceived, this,
                 [this, name, password, stream]() {
                     if (m_userName != name) {
                         m_userName = name;
                         m_password = password;
                         emit userNameChanged();
                     }
                     setState(Connected);
                     m_messages.append(
                             stream->read<qtgrpc::examples::chat::ChatMessages>().messages());
                 });

QGrpcServerStream 处理程序提供客户端应用程序应连接到的信号。

指示服务器侧或通信通道中发生的错误的 QGrpcServerStream::errorOccurred 信号。通常,错误会导致与服务器连接关闭,并且发出 QGrpcServerStream::finished 信号。

当服务器向流发送新消息时,QGrpcServerStream 发射 QGrpcServerStream::messageReceived 信号。连接到此信号的槽处理聊天消息。从 SimpleChat/messageList 服务器流接收到的消息收集到自定义 QAbstractListModel 模型中,并向用户显示。

当发出 QGrpcServerStream::finished 信号时,您无法在此流实例上做任何事情,因此您需要启动新的订阅。

订阅成功后,聊天客户端切换到对话屏幕,允许您查看和发送简短消息

要发送消息,使用单元 RPC 调用 SimpleChat/sendMessage。客户端应用程序首先设置 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);
m_client->sendMessage(msg);

然后,gRPC 服务器处理客户端消息并通过 SimpleChat/messageList 流将它们广播给所有已连接的客户端。

注意:此示例在服务器实现中使用了参考 gRPC C++ API。

示例项目 @ code.qt.io

© 2024 Qt公司有限公司。本文件中的文档贡献归各自所有者所有版权。本文件提供的文档根据自由软件基金会发布的©GNU自由文档许可协议第1.3版进行许可。Qt及其相关标志是芬兰以及世界其他国家和地区的Qt公司有限公司的商标。商标