WIP-How to create a simple chat application: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 50: Line 50:
{| class="wikitable"
{| class="wikitable"
|-
|-
! Private Members  
! colspan="2" | Private Members  
|-
| <tt>m_clientSocket</tt> || The socket that will interact with the server
| <tt>m_clientSocket</tt> || The socket that will interact with the server
|-
|-
| <tt>m_loggedIn</tt> || Used to record whether the client already agreed a username with the server or not
| <tt>m_loggedIn</tt> || Used to record whether the client already agreed a username with the server or not
|-
! colspan="2" | Private Methods and Slots
|-
| <tt>onReadyRead()</tt> || Slot that reacts to data being available on the socket. It will download the data and pass it to <tt>jsonReceived()</tt>
|-
|-
| <tt>jsonReceived()</tt> || Method to process the messages received from the server
| <tt>jsonReceived()</tt> || Method to process the messages received from the server
|-
|-
| <tt>jsonReceived()</tt> || Example
! colspan="2" | Signals
|-
| <tt>connected()</tt> || The client connected to the server successfully
|-
| <tt>disconnected()</tt> || The client is not connected any more
|-
|-
| Example || Example
| <tt>loggedIn()</tt> || The client successfully agreed a username with the server
|-
|-
| Example || Example
| <tt>loginError()</tt> || The server rejected the username provided
|-
|-
| Example || Example
| <tt>messageReceived()</tt> || The client received a chat message
|-
|-
| Example || Example
| <tt>userJoined()</tt> || A new user joined the chat
|-
|-
| Example || Example
| <tt>userLeft()</tt> || A user left the chat
|-
|-
| Example || Example
| <tt>error()</tt> || Just a forward of the [http://doc.qt.io/qt-5/qabstractsocket.html#error QTcpSocket::error signal]
|-
|-
| Example || Example
! colspan="2" | Public Slots
|-
|-
| Example || Example
| <tt>connectToServer()</tt> || Attempts the connection to a server
|-
|-
| Example || Example
| <tt>login()</tt> || Attempts to agree the given username with the server
|-
|-
| Example || Example
| <tt>disconnectFromHost()</tt> || Closes the connection with the server
|-
|-
| Example || Example
| <tt>sendMessage()</tt> || Sends a chat message to the server
|-
|-
| Example || Example
|}
|}
* <tt>

Revision as of 10:49, 1 June 2018

Introduction

This article will illustrate a simple chat client and server communicating over TCP. The aim is to clarify aspects of QTcpSocket/QTcpServer that are not developed in the official Qt Fortune example. This has no intention to be a fully featured chat application.

You can find the source code relating to this example on GitHub

Pre-Requisites

An intermediate level of knowledge of Qt Familiarity with C++11 concepts, especially lambdas and std::bind

The Logic

This application will use a central server that will manage the communication among clients via JSON messages. We'll implement 2 versions of the server, one that runs in a single server and one that distributes the sockets among multiple threads.

The Client

The client in this example is a simple QtWidgets application, the ui is minimal, just a button to connect to the server, a list view to display the messages received, a line edit to type your messages and a button to send them.

The core of the functionality is in the ChatClient class.

class ChatClient : public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(ChatClient)
public:
    explicit ChatClient(QObject *parent = nullptr);
public slots:
    void connectToServer(const QHostAddress &address, quint16 port);
    void login(const QString &userName);
    void sendMessage(const QString &text);
    void disconnectFromHost();
private slots:
    void onReadyRead();
signals:
    void connected();
    void loggedIn();
    void loginError(const QString &reason);
    void disconnected();
    void messageReceived(const QString &sender, const QString &text);
    void error(QAbstractSocket::SocketError socketError);
    void userJoined(const QString &username);
    void userLeft(const QString &username);
private:
    QTcpSocket *m_clientSocket;
    bool m_loggedIn;
    void jsonReceived(const QJsonObject &doc);
};

Let's break down what each of these methods and member does:


Private Members
m_clientSocket The socket that will interact with the server
m_loggedIn Used to record whether the client already agreed a username with the server or not
Private Methods and Slots
onReadyRead() Slot that reacts to data being available on the socket. It will download the data and pass it to jsonReceived()
jsonReceived() Method to process the messages received from the server
Signals
connected() The client connected to the server successfully
disconnected() The client is not connected any more
loggedIn() The client successfully agreed a username with the server
loginError() The server rejected the username provided
messageReceived() The client received a chat message
userJoined() A new user joined the chat
userLeft() A user left the chat
error() Just a forward of the QTcpSocket::error signal
Public Slots
connectToServer() Attempts the connection to a server
login() Attempts to agree the given username with the server
disconnectFromHost() Closes the connection with the server
sendMessage() Sends a chat message to the server