채팅

사용자 애플리케이션에서 Qt GRPC 클라이언트 API를 사용합니다.

채팅에서는 채팅 사용자를 인증하고 채팅 클라이언트 간에 단문 메시지를 주고받는 방법에 대해 설명합니다. 이 애플리케이션은 다음과 같은 메시지 형식을 지원합니다:

  • 텍스트 - 메시지 입력 필드를 사용하여 메시지를 보냅니다.
  • 이미지 - 이미지 버퍼를 클립보드에 복사하여 'Ctrl + V' 바로가기를 사용하여 메시지를 보냅니다.

채팅 클라이언트는 프로토뷰 체계에 설명된 간단한 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 서버 스트리밍 구독을 사용하여 서버와의 통신을 시작합니다:

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 을 사용합니다. 클라이언트 애플리케이션은 먼저 ChatMessage 프로토뷰 메시지의 필드를 설정한 다음 클라이언트 메서드를 호출합니다:

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);// 회신 포인터를 람다로 이동하면// get() 함수가 유효하지 않으므로 명시적으로 복사본을 가져옵니다. // 회신 수명은 finished() 가 나올 때까지 연장됩니다. // 람다 (및 그 캡처)를 파괴하려면 Qt::SingleShotConnection이 필요합니다.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 참조를 사용합니다.

예제 프로젝트 @ 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.