C++17 and Qt6 Network Programming: Building a High-Performance Server Architecture from TCP Protocol to SQLite3

C++17 and Qt6 Network Programming: Building a High-Performance Server Architecture from TCP Protocol to SQLite3

Welcome to the 【Ultimate Programming】 WeChat public account 【Knowledge Repository】, specially customized for everyone《Qt C++ Architect》 Series – Project Practice Episode 138:This issue will focus on a practical and challenging technical topic –【C++17 and Qt6 Network Programming: Building a High-Performance Server Architecture from TCP Protocol to SQLite3】.Whether you are a beginner who has just mastered the Qt cross-platform framework and Linux C/C++ backend server development, or a developer who wants to delve into the research of C/C++ system architecture, this technology will open a door to deep learning for you.

【Development Environment】: Win10 x64, Qt version 6.8;

【Daily sharing of high-quality projects and cutting-edge technical programming content!】

【Follow the UP master and join the QQ group】: 【895876809 Download project source code (for research and study)】.

1: 【Project】📁 Source Structure

C++17 and Qt6 Network Programming: Building a High-Performance Server Architecture from TCP Protocol to SQLite3

2: 【Project】🚀 Running Results

1: Server – Start

C++17 and Qt6 Network Programming: Building a High-Performance Server Architecture from TCP Protocol to SQLite3

2: Client – Connect

C++17 and Qt6 Network Programming: Building a High-Performance Server Architecture from TCP Protocol to SQLite3

3: 【Project】🏗️ Project Overview and Features

1: Project Overview

  • Language/Framework:C++17, Qt Widgets, Qt Network, Qt SQL

  • Running End: Desktop Client (ClientWindow) and Desktop Server (ServerWindow)

  • Communication Protocol: TCP (UTF-8 text)

  • Data Storage: SQLite (local files: client_history.db, chat_history.db)

  • Verified Environment: Windows 10, Qt 6.5.3 MinGW 64-bit (also compatible with Qt 5.15+)

2: Features

2.1 Client (ClientWindow)

  • Connect and Disconnect: Input server IP/port, one-click connect/disconnect

  • Real-time Communication: Send messages, receive server messages, rich text beautification display

  • History: SQLite automatic persistence, loads the last 50 entries on startup, clicking history can refill the input box

  • Robustness: Network and database error prompts, status change prompts

2.2 Server (ServerWindow)

  • Service Management: Specify IP/port to start/stop listening

  • Connection Management: Accept multiple client connections, automatically clean up disconnections

  • Message Distribution: Broadcast to all connected clients

  • History: SQLite automatic persistence, displays the last 50 system/send/receive messages

  • User-friendly UI: Unified style, grouped layout, automatic scrolling

  • 4: 【Project】📋 Source Code Analysis

1: clientwindow.h file

// ClientWindow.h (unchanged)#ifndef CLIENTWINDOW_H#define CLIENTWINDOW_H
#include <QWidget>
#include <QTcpSocket>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDateTime>
class QTextEdit;class QLineEdit;class QListWidget;class QPushButton;
class ClientWindow : public QWidget{    Q_OBJECT
public:    explicit ClientWindow(QWidget *parent = nullptr);    ~ClientWindow();
private slots:    void connectServer();    void disconnectServer();    void sendMessage();    void socketConnected();    void socketDisconnected();    void socketReadyRead();    void loadHistory();    void handleError(QAbstractSocket::SocketError error);
private:    void setupUI();    void setupDatabase();    void saveMessage(const QString &message, bool isOutgoing);
    QTcpSocket *tcpSocket;    QSqlDatabase db;
    QLineEdit *ipEdit;    QLineEdit *portEdit;    QPushButton *connectBtn;    QPushButton *disconnectBtn;    QTextEdit *msgDisplay;    QLineEdit *msgInput;    QListWidget *historyList;};
#endif // CLIENTWINDOW_H

2: clientwindow.cpp file

// ClientWindow.cpp (beautified full version)#include "ClientWindow.h"#include <QVBoxLayout>#include <QHBoxLayout>#include <QLabel>#include <QMessageBox>#include <QScrollBar>#include <QDateTime>#include <QFont>#include <QDebug>
#include <QApplication>#include <QLineEdit>#include <QPushButton>#include <QTextEdit>#include <QListWidget>#include <QSqlError>

ClientWindow::ClientWindow(QWidget *parent)    : QWidget(parent), tcpSocket(nullptr){    setMinimumSize(960, 720);
    setupUI();    setupDatabase();    loadHistory();}
ClientWindow::~ClientWindow(){    if(tcpSocket) tcpSocket->close();    db.close();}
void ClientWindow::setupUI(){    // Basic window settings    setWindowTitle("Chat Client Pro");    //  setMinimumSize(1000, 200);    setStyleSheet("background-color: #f8f9fa;");
    // Set global font    QFont font("Microsoft YaHei", 10);    QApplication::setFont(font);
    // ================= Connection Area =================    ipEdit = new QLineEdit();    ipEdit->setPlaceholderText("Server IP");    ipEdit->setText("127.0.0.1");    ipEdit->setStyleSheet(R"(
        QLineEdit {
            padding: 12px;
            border: 2px solid #dee2e6;
            border-radius: 8px;
            background: white;
            font-size: 14px;
        }
        QLineEdit:focus {
            border-color: #4dabf7;
            outline: none;
        }
    )");
    portEdit = new QLineEdit();    portEdit->setPlaceholderText("Port");    portEdit->setText("12345");    portEdit->setFixedWidth(150);    portEdit->setStyleSheet(ipEdit->styleSheet());
    // Button styles    QString btnStyle = R"(
        QPushButton {
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            color: white;
            font-weight: 500;
            font-size: 14px;
            min-width: 120px;
            transition: all 0.3s;
        }
        QPushButton:hover {
            opacity: 0.9;
            transform: translateY(-1px);
        }
        QPushButton:pressed {
            opacity: 0.8;
            transform: translateY(0);
        }
        QPushButton:disabled {
            background: #adb5bd !important;
        }
    )";
    connectBtn = new QPushButton("🔗 Connect");    disconnectBtn = new QPushButton("🚫 Disconnect");    connectBtn->setStyleSheet(btnStyle + "background: #4dabf7;");    disconnectBtn->setStyleSheet(btnStyle + "background: #ff6b6b;");    disconnectBtn->setEnabled(false);
    QHBoxLayout *connLayout = new QHBoxLayout();    connLayout->addWidget(ipEdit);    connLayout->addWidget(portEdit);    connLayout->addWidget(connectBtn);    connLayout->addWidget(disconnectBtn);    connLayout->setSpacing(20);    connLayout->setContentsMargins(0, 0, 0, 20);
    // ================= Message Display Area =================    msgDisplay = new QTextEdit;    msgDisplay->setPlaceholderText("Message history will appear here...");    msgDisplay->setStyleSheet(R"(
        QTextEdit {
            background: white;
            border: 2px solid #dee2e6;
            border-radius: 12px;
            padding: 16px;
            font-size: 14px;
            color: #495057;
        }
        QScrollBar:vertical {
            width: 12px;
            background: #f1f3f5;
            border-radius: 6px;
        }
        QScrollBar::handle:vertical {
            background: #ced4da;
            border-radius: 6px;
            min-height: 30px;
        }
        QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
            height: 0;
        }
    )");    msgDisplay->setMinimumHeight(300);
    // ================= History =================    historyList = new QListWidget;    historyList->setStyleSheet(R"(
        QListWidget {
            background: white;
            border: 2px solid #dee2e6;
            border-radius: 12px;
            padding: 4px;
        }
        QListWidget::item {
            padding: 12px;
            border-bottom: 1px solid #dee2e6;
            color: #495057;
            font-size: 13px;
        }
        QListWidget::item:hover {
            background: #e9ecef;
        }
        QListWidget::item:selected {
            background: #4dabf7;
            color: white;
        }
    )");    historyList->setMaximumHeight(180);    connect(historyList, &QListWidget::itemClicked, [this](QListWidgetItem *item){        msgInput->setText(item->data(Qt::UserRole).toString());    });
    // ================= Message Input Area =================    msgInput = new QLineEdit;    msgInput->setPlaceholderText("Type your message...");    msgInput->setStyleSheet(R"(
        QLineEdit {
            padding: 16px;
            border: 2px solid #4dabf7;
            border-radius: 8px;
            background: white;
            font-size: 14px;
        }
        QLineEdit:focus {
            border-color: #339af0;
            outline: none;
        }
    )");
    QPushButton *sendBtn = new QPushButton("🚀 Send");    sendBtn->setFixedWidth(150);    sendBtn->setStyleSheet(btnStyle + "background-color: #44bd32;"                                      "color: white;"                                      "background-color: #3a9b2a;");

    QHBoxLayout *inputLayout = new QHBoxLayout;    inputLayout->addWidget(msgInput);    inputLayout->addWidget(sendBtn);    inputLayout->setSpacing(20);
    // ================= Main Layout =================    QVBoxLayout *mainLayout = new QVBoxLayout(this);    mainLayout->addLayout(connLayout);    mainLayout->addWidget(msgDisplay, 1);    mainLayout->addWidget(new QLabel("📜 Message History"));    mainLayout->addWidget(historyList);    mainLayout->addLayout(inputLayout);    mainLayout->setSpacing(20);    mainLayout->setContentsMargins(30, 30, 30, 30);
    // Signal connections    connect(connectBtn, &QPushButton::clicked, this, &ClientWindow::connectServer);    connect(disconnectBtn, &QPushButton::clicked, this, &ClientWindow::disconnectServer);    connect(sendBtn, &QPushButton::clicked, this, &ClientWindow::sendMessage);    connect(msgInput, &QLineEdit::returnPressed, this, &ClientWindow::sendMessage);}
void ClientWindow::setupDatabase(){    db = QSqlDatabase::addDatabase("QSQLITE", "client_connection");    db.setDatabaseName("client_history.db");
    if(!db.open()){        QMessageBox::critical(this, "Database Error",                              "Failed to open database!\nError: " + db.lastError().text());        return;
    }
    QSqlQuery query(db);    QString createTable = R"(
        CREATE TABLE IF NOT EXISTS messages (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            timestamp DATETIME NOT NULL,
            content TEXT NOT NULL,
            direction INTEGER NOT NULL
        )
    )";
    if(!query.exec(createTable)){        QMessageBox::critical(this, "Database Error",                              "Create table failed: " + query.lastError().text());    }}
void ClientWindow::connectServer(){    if(tcpSocket) return;
    tcpSocket = new QTcpSocket(this);    connect(tcpSocket, &QTcpSocket::connected, this, &ClientWindow::socketConnected);    connect(tcpSocket, &QTcpSocket::disconnected, this, &ClientWindow::socketDisconnected);    connect(tcpSocket, &QTcpSocket::readyRead, this, &ClientWindow::socketReadyRead);    connect(tcpSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::errorOccurred),            this, &ClientWindow::handleError);
    QString ip = ipEdit->text().trimmed();    int port = portEdit->text().toInt();
    if(ip.isEmpty() || port <= 0){        QMessageBox::warning(this, "Error", "Invalid server address or port!");        return;
    }
    tcpSocket->connectToHost(ip, port);    msgDisplay->append("<div style='color:#868e96;'>Connecting to server...</div>");}
void ClientWindow::disconnectServer(){    if(tcpSocket){        tcpSocket->disconnectFromHost();        tcpSocket->deleteLater();        tcpSocket = nullptr;
    }    connectBtn->setEnabled(true);    disconnectBtn->setEnabled(false);    msgDisplay->append("<div style='color:#868e96;'>Disconnected from server</div>");}
void ClientWindow::sendMessage(){    if(!tcpSocket || tcpSocket->state() != QAbstractSocket::ConnectedState){        QMessageBox::warning(this, "Error", "Not connected to server!");        return;
    }
    QString message = msgInput->text().trimmed();    if(message.isEmpty()) return;
    QByteArray data = message.toUtf8();    tcpSocket->write(data);
    // Beautify message display    QString time = QDateTime::currentDateTime().toString("hh:mm:ss");    msgDisplay->append(QString(R"(
        <div style="margin:12px 0; padding:12px;                   background:#e3fafc;                   border-radius:8px;                   border:1px solid #99e9f2;">            <div style="color:#0c8599; font-weight:500;">[You]                <span style="color:#868e96; font-size:12px;">%1</span>            </div>            <div style="margin-top:6px; color:#087f5b;">%2</div>        </div>    )").arg(time).arg(message.toHtmlEscaped()));
    saveMessage(message, true);    msgInput->clear();
    // Auto-scroll to bottom    QScrollBar *scrollBar = msgDisplay->verticalScrollBar();    scrollBar->setValue(scrollBar->maximum());}
void ClientWindow::socketConnected(){    connectBtn->setEnabled(false);    disconnectBtn->setEnabled(true);    msgDisplay->append(R"(
        <div style="color:#2b8a3e; font-weight:500;">            ✓ Connected to server successfully!        </div>    )");}
void ClientWindow::socketDisconnected(){    disconnectServer();}
void ClientWindow::socketReadyRead(){    QByteArray data = tcpSocket->readAll();    QString message = QString::fromUtf8(data);
    // Beautify server message display    QString time = QDateTime::currentDateTime().toString("hh:mm:ss");    msgDisplay->append(QString(R"(
        <div style="margin:12px 0; padding:12px;                   background:#fff4e6;                   border-radius:8px;                   border:1px solid #ffd8a8;">            <div style="color:#d9480f; font-weight:500;">[Server]                <span style="color:#868e96; font-size:12px;">%1</span>            </div>            <div style="margin-top:6px; color:#a61e4d;">%2</div>        </div>    )").arg(time).arg(message.toHtmlEscaped()));
    saveMessage(message, false);
    // Auto-scroll    QScrollBar *scrollBar = msgDisplay->verticalScrollBar();    scrollBar->setValue(scrollBar->maximum());}

3: serverwindow.h file

// ServerWindow.h#ifndef SERVERWINDOW_H#define SERVERWINDOW_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDateTime>
#include <QGroupBox>
class QTextEdit;class QLineEdit;class QListWidget;class QPushButton;
class ServerWindow : public QWidget{    Q_OBJECT
public:    explicit ServerWindow(QWidget *parent = nullptr);    ~ServerWindow();
private slots:    void startServer();    void stopServer();    void sendMessage();    void newConnection();    void readData();    void clientDisconnected();    void loadHistory();
private:    void setupUI();    void setupDatabase();    void saveMessage(const QString &message, bool isOutgoing);    void appendMessage(const QString &message, bool isOutgoing);
    QTcpServer *tcpServer;    QList<QTcpSocket*> clients;    QSqlDatabase db;
    // UI components    QLineEdit *ipEdit;    QLineEdit *portEdit;    QPushButton *startBtn;    QPushButton *stopBtn;    QTextEdit *msgDisplay;    QLineEdit *msgInput;    QListWidget *historyList;};
#endif // SERVERWINDOW_H

4: ServerWindow.cpp file

// ServerWindow.cpp#include "ServerWindow.h"#include <QVBoxLayout>#include <QHBoxLayout>#include <QGroupBox>#include <QLabel>#include <QMessageBox>#include <QScrollBar>#include <QLineEdit>#include <QPushButton>#include <QTextEdit>#include <QListWidget>#include <QFontDatabase>#include <QDateTime>
// Modified global stylesheet definitionconst QString appStyleSheet = R"(
    /* Main window style */    QWidget {
        background-color: #f5f6fa;
        font-family: 'Microsoft YaHei';
        font-size: 14px;
    }
    /* Group box style */    QGroupBox {
        border: 1px solid #dcdde1;
        border-radius: 8px;
        margin-top: 20px;
        padding-top: 25px;
        color: #2f3640;
        font-weight: 500;
        background-color: white;
    }
    QGroupBox::title {
        subcontrol-origin: margin;
        left: 15px;
        padding: 0 8px;
        color: #718093;
    }
    /* Message display area */    QTextEdit {
        background-color: white;
        border: 1px solid #dcdde1;
        border-radius: 6px;
        padding: 12px;
        color: #2f3640;
        selection-background-color: #a4b0be;
    }
    /* History list */    QListWidget {
        background-color: white;
        border: 1px solid #dcdde1;
        border-radius: 6px;
        padding: 6px;
        color: #2f3640;
        alternate-background-color: #f5f6fa;
    }
    QListWidget::item {
        padding: 8px 12px;
        border-bottom: 1px solid #f5f6fa;
    }
    QListWidget::item:hover {
        background-color: #eef0f3;
    }
    /* Input box style */    QLineEdit {
        border: 2px solid #dcdde1;
        border-radius: 6px;
        padding: 10px;
        color: #2f3640;
        font-size: 14px;
    }
    QLineEdit:focus {
        border-color: #487eb0;
        outline: none;
    }
    /* Button common style */    QPushButton {
        border: none;
        padding: 10px 24px;
        border-radius: 6px;
        font-weight: 500;
        min-width: 100px;
        transition: all 0.2s ease;
    }
    /* Start button */    #startBtn {
        background-color: #487eb0;
        color: white;
    }
    #startBtn:hover {
        background-color: #40739e;
    }
    #startBtn:disabled {
        background-color: #dcdde1;
    }
    /* Stop button */    #stopBtn {
        background-color: #e84118;
        color: white;
    }
    #stopBtn:hover {
        background-color: #c23616;
    }
    /* Send button */    #sendBtn {
        background-color: #44bd32;
        color: white;
    }
    #sendBtn:hover {
        background-color: #3a9b2a;
    }
    /* Scrollbar style */    QScrollBar:vertical {
        width: 12px;
        background: #f5f6fa;
    }
    QScrollBar::handle:vertical {
        background: #a4b0be;
        border-radius: 6px;
        min-height: 30px;
    }
)";
ServerWindow::ServerWindow(QWidget *parent)    : QWidget(parent), tcpServer(nullptr){    setStyleSheet(appStyleSheet);   // setWindowTitle("Chat Server - Professional Edition");    setMinimumSize(960, 720);
    setupUI();    setupDatabase();    loadHistory();}
ServerWindow::~ServerWindow(){    if(tcpServer) tcpServer->close();    db.close();}
void ServerWindow::setupUI(){    // Server configuration group    QGroupBox *serverGroup = new QGroupBox("Server Configuration");    ipEdit = new QLineEdit("127.0.0.1");    portEdit = new QLineEdit("12345");    startBtn = new QPushButton("Start Service");    stopBtn = new QPushButton("Stop Service");
    startBtn->setObjectName("startBtn");    stopBtn->setObjectName("stopBtn");    stopBtn->setEnabled(false);
    // Server layout    QHBoxLayout *serverLayout = new QHBoxLayout;    serverLayout->addWidget(new QLabel("Server IP:" ));    serverLayout->addWidget(ipEdit);    serverLayout->addWidget(new QLabel("Port:" ));    serverLayout->addWidget(portEdit);    serverLayout->addStretch();    serverLayout->addWidget(startBtn);    serverLayout->addWidget(stopBtn);    serverGroup->setLayout(serverLayout);
    // Message display area    msgDisplay = new QTextEdit;    msgDisplay->setReadOnly(true);    msgDisplay->document()->setDefaultStyleSheet(R"(
        .message {
            margin: 10px 0;
            padding: 8px 12px;
            border-radius: 6px;
            background: #f5f6fa;
        }
        .server {
            color: #487eb0;
            font-weight: 500;
        }
        .client {
            color: #44bd32;
            font-weight: 500;
        }
        .timestamp {
            color: #718093;
            font-size: 12px;
        }
        .system {
            color: #e84118;
            font-style: italic;
        }
    )");
    // History group    QGroupBox *historyGroup = new QGroupBox("History Messages (Last 50)");    historyList = new QListWidget;    historyList->setAlternatingRowColors(true);    historyList->setMaximumHeight(140);
    QVBoxLayout *historyLayout = new QVBoxLayout;    historyLayout->setContentsMargins(2, 10, 2, 2);    historyLayout->addWidget(historyList);    historyGroup->setLayout(historyLayout);
    // Message input group    QGroupBox *inputGroup = new QGroupBox("Message Sending");    msgInput = new QLineEdit;    msgInput->setPlaceholderText("Enter message content (press Enter to send)...");    QPushButton *sendBtn = new QPushButton("Send");    sendBtn->setObjectName("sendBtn");
    QHBoxLayout *inputLayout = new QHBoxLayout;    inputLayout->addWidget(msgInput, 1);    inputLayout->addWidget(sendBtn);    inputGroup->setLayout(inputLayout);
    // Main layout    QVBoxLayout *mainLayout = new QVBoxLayout(this);    mainLayout->setContentsMargins(20, 20, 20, 20);    mainLayout->setSpacing(15);    mainLayout->addWidget(serverGroup);    mainLayout->addWidget(msgDisplay, 1);    mainLayout->addWidget(historyGroup);    mainLayout->addWidget(inputGroup);
    // Signal connections    connect(startBtn, &QPushButton::clicked, this, &ServerWindow::startServer);    connect(stopBtn, &QPushButton::clicked, this, &ServerWindow::stopServer);    connect(sendBtn, &QPushButton::clicked, this, &ServerWindow::sendMessage);    connect(msgInput, &QLineEdit::returnPressed, this, &ServerWindow::sendMessage);}

Due to space limitations, follow the UP master to join the group and download the project source code for research and study.

Leave a Comment