[Qt entrou pela primeira vez em rios e lagos] Exemplo de implementação de sala de bate-papo Qt

Yuxian: parceiro de conteúdo da CSDN, novo mentor estrela da CSDN, 51CTO (principal celebridade + blogueiro especialista), entusiasta de código aberto do github (desenvolvimento secundário de código-fonte go-zero, arquitetura de back-end de jogos https://github.com/Peakchen)

 

Qt chat room é um software de chat em tempo real baseado em comunicação em rede, que geralmente consiste em duas partes: cliente e servidor. Neste artigo, apresentaremos detalhadamente a arquitetura subjacente, os princípios e os métodos de implementação da sala de chat Qt.

A arquitetura subjacente da sala de chat do Qt consiste nas seguintes partes:

  1. Servidor QTcp

QTcpServer é uma classe usada para implementar um servidor TCP em Qt. Ele pode escutar uma porta especificada e aguardar uma solicitação de conexão de um cliente. Na sala de chat do Qt, podemos usar o QTcpServer para monitorar a solicitação de conexão do cliente.

  1. QTcpSocket

QTcpSocket é uma classe usada para implementar um cliente TCP no Qt, que pode se conectar a um servidor especificado e enviar e receber dados. Na sala de chat do Qt, podemos usar QTcpSocket para conectar-se ao servidor e enviar e receber mensagens de chat.

  1. QThread

QThread é uma classe usada para implementar threads em Qt, que pode atribuir tarefas a diferentes threads para execução. Na sala de bate-papo do Qt, podemos usar QThread para realizar comunicação de rede e atualização da IU separadamente para evitar o bloqueio do thread da IU.

  1. QDataStream

QDataStream é uma classe usada para implementar fluxos de dados no Qt. Ele pode serializar dados em fluxos binários e desserializar fluxos binários em dados. Na sala de chat do Qt, podemos usar QDataStream para serializar a mensagem de chat em um fluxo binário e enviá-la ao servidor ou outros clientes.

A seguir está um diagrama de arquitetura de implementação de uma sala de bate-papo simples baseada em TCP:

+-----------------+
|   ServerSocket  |
+-----------------+
| - tcpServer     |
| - clientSockets |
+-----------------+
          /_\
           |
           | 继承
           |
+-----------------+
|   QTcpServer    |
+-----------------+
          /_\
           |
           | 继承
           |
+-----------------+
|   QTcpSocket    |
+-----------------+

Neste framework, a classe ServerSocket herda da classe QTcpServer, que é responsável por monitorar a solicitação de conexão do cliente e criar o soquete do cliente correspondente. Quando um novo cliente se conecta, ServerSocket criará um novo objeto ClientSocket (herdado da classe QTcpSocket) para lidar com a comunicação com o cliente. A função slot na classe ClientSocket é usada para receber a mensagem enviada pelo cliente e transmiti-la para outros clientes.

Na sala de chat do Qt, podemos usar os seguintes métodos para implementar a função de chat:

  1. QTcpServer::ouvir()

O método listen() é usado para iniciar a escuta na porta especificada e aceita um parâmetro do tipo inteiro indicando o número da porta a ser escutada. Por exemplo:

QTcpServer server;
server.listen(QHostAddress::Any, 1234);
  1. QTcpServer::newConnection()

O sinal newConnection() é acionado quando há uma nova solicitação de conexão do cliente. Podemos criar um novo objeto QTcpSocket na função slot do sinal e conectá-lo ao cliente. Por exemplo:

QTcpServer server;
server.listen(QHostAddress::Any, 1234);

connect(&server, &QTcpServer::newConnection, [&]() {
    QTcpSocket *clientSocket = server.nextPendingConnection();
    // 将clientSocket添加到客户端列表中
});
  1. QTcpSocket::connectToHost()

O método connectToHost() é usado para conectar-se ao servidor especificado. Ele aceita um parâmetro do tipo string, indicando o nome do host ou endereço IP do servidor a ser conectado, e um parâmetro do tipo inteiro, indicando o número da porta do servidor. estar conectado. Por exemplo:

QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("127.0.0.1", 1234);
  1. QTcpSocket::conectado()

O sinal conectado() é acionado quando conectado com sucesso ao servidor, e podemos enviar uma mensagem de login ao servidor na função slot do sinal. Por exemplo:

QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("127.0.0.1", 1234);

connect(socket, &QTcpSocket::connected, [&]() {
    QByteArray username = "username";
    QByteArray password = "password";
    QDataStream stream(socket);
    stream << username << password;
});
  1. QTcpSocket::readyRead()

O sinal readyRead() é acionado quando há dados para ler, e podemos receber mensagens de chat na função slot do sinal e exibi-las na UI. Por exemplo:

QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("127.0.0.1", 1234);

connect(socket, &QTcpSocket::readyRead, [&]() {
    QDataStream stream(socket);
    QString message;
    stream >> message;
    // 将message显示在UI上
});
  1. QTcpSocket::disconnected()

O sinal desconectado() é acionado quando a conexão com o servidor é desconectada e podemos limpar os recursos relacionados na função de slot do sinal. Por exemplo:

QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("127.0.0.1", 1234);

connect(socket, &QTcpSocket::disconnected, [&]() {
    // 清理相关资源
});
  1. QThread::start()

O método start() é usado para iniciar o thread e chamará automaticamente o método run() do thread. Por exemplo:

QThread *thread = new QThread;
MyNetworkWorker *worker = new MyNetworkWorker;

worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &MyNetworkWorker::run);
connect(worker, &MyNetworkWorker::finished, thread, &QThread::quit);
connect(worker, &MyNetworkWorker::finished, worker, &MyNetworkWorker::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);

thread->start();
  1. QDataStream::operator<<() e QDataStream::operator>>()

O método operador<<() é usado para serializar dados em um fluxo binário, e o método operador>>() é usado para desserializar um fluxo binário em dados. Por exemplo:

QByteArray username = "username";
QByteArray password = "password";
QDataStream stream(&buffer, QIODevice::WriteOnly);
stream << username << password;

// ...

QDataStream stream(socket);
QString message;
stream >> message;

A seguir está um exemplo de implementação de uma sala de chat Qt simples, que inclui o uso dos métodos acima:

class ChatServer : public QObject
{
    Q_OBJECT

public:
    ChatServer(QObject *parent = nullptr) : QObject(parent)
    {
        server = new QTcpServer(this);
        connect(server, &QTcpServer::newConnection, this, &ChatServer::onNewConnection);
        server->listen(QHostAddress::Any, 1234);

        qInfo() << "Server started";
    }

signals:
    void messageReceived(QString message);

public slots:
    void onNewConnection()
    {
        QTcpSocket *clientSocket = server->nextPendingConnection();
        connect(clientSocket, &QTcpSocket::disconnected, clientSocket, &QTcpSocket::deleteLater);
        connect(clientSocket, &QTcpSocket::readyRead, this, &ChatServer::onMessageReceived);
        clients.append(clientSocket);
    }

    void onMessageReceived()
    {
        QTcpSocket *clientSocket = qobject_cast<QTcpSocket*>(sender());
        QDataStream stream(clientSocket);
        QString message;
        stream >> message;
        emit messageReceived(message);
    }

    void sendMessage(QString message)
    {
        QByteArray buffer;
        QDataStream stream(&buffer, QIODevice::WriteOnly);
        stream << message;

        for (QTcpSocket *clientSocket : clients) {
            clientSocket->write(buffer);
        }
    }

private:
    QTcpServer *server;
    QList<QTcpSocket*> clients;
};

class ChatClient : public QObject
{
    Q_OBJECT

public:
    ChatClient(QObject *parent = nullptr) : QObject(parent)
    {
        socket = new QTcpSocket(this);
        connect(socket, &QTcpSocket::connected, this, &ChatClient::onConnected);
        connect(socket, &QTcpSocket::disconnected, this, &ChatClient::onDisconnected);
        connect(socket, &QTcpSocket::readyRead, this, &ChatClient::onMessageReceived);
        socket->connectToHost("127.0.0.1", 1234);

        qInfo() << "Client started";
    }

public slots:
    void onConnected()
    {
        QByteArray username = "username";
        QByteArray password = "password";
        QDataStream stream(socket);
        stream << username << password;
    }

    void onDisconnected()
    {
        qInfo() << "Disconnected from server";
    }

    void onMessageReceived()
    {
        QDataStream stream(socket);
        QString message;
        stream >> message;
        qInfo() << "Received message:" << message;
    }

    void sendMessage(QString message)
    {
        QByteArray buffer;
        QDataStream stream(&buffer, QIODevice::WriteOnly);
        stream << message;
        socket->write(buffer);
    }

private:
    QTcpSocket *socket;
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    ChatServer server;
    ChatClient client;

    QObject::connect(&server, &ChatServer::messageReceived, &client, &ChatClient::sendMessage);
    QObject::connect(&client, &ChatClient::messageReceived, &server, &ChatServer::sendMessage);

    return app.exec();
}

Neste exemplo de implementação, o servidor e o cliente são representados pela classe ChatServer e pela classe ChatClient respectivamente

Acho que você gosta

Origin blog.csdn.net/feng1790291543/article/details/131807334
Recomendado
Clasificación