自学内容网 自学内容网

Every newconnection, use a thread.

To modify your existing TCP server implementation in the MainWindow class so that every new connection is handled in its own separate thread, you'll need to create a QThread for each new connection. This can be achieved by creating a dedicated class to handle client connections and managing it within its thread.

Here's how you can do it:

1. Create ClientHandler Class

We'll create a ClientHandler class that will handle the communication with the client. This class will inherit from QObject, and it will utilize a QTcpSocket for communication.

Header File: ClientHandler.h
 

cpp

#ifndef CLIENTHANDLER_H
#define CLIENTHANDLER_H

#include <QObject>
#include <QTcpSocket>

class ClientHandler : public QObject
{
    Q_OBJECT

public:
    explicit ClientHandler(qintptr socketDescriptor, QObject *parent = nullptr);
    void process();

signals:
    void disconnected();

private slots:
    void onReadyRead();
    void onDisconnected();

private:
    QTcpSocket *clientSocket;
};

#endif // CLIENTHANDLER_H

cpp

Source File: ClientHandler.cpp
 

cpp

#include "ClientHandler.h"
#include <QDebug>

ClientHandler::ClientHandler(qintptr socketDescriptor, QObject *parent)
    : QObject(parent)
{
    clientSocket = new QTcpSocket(this);
    
    if (clientSocket->setSocketDescriptor(socketDescriptor)) {
        connect(clientSocket, &QTcpSocket::readyRead, this, &ClientHandler::onReadyRead);
        connect(clientSocket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected);
    } else {
        emit disconnected();
    }
}

void ClientHandler::onReadyRead()
{
    QByteArray data = clientSocket->readAll();
    qDebug() << "Data received from client: " << data;

    // Process data and send response
    QString response = "Server received: " + QString::number(data.size()) + " bytes.";
    clientSocket->write(response.toUtf8());
}

void ClientHandler::onDisconnected()
{
    qDebug() << "Client disconnected.";
    emit disconnected();
    clientSocket->deleteLater();
}

cpp

2. Modify the MainWindow

Now we'll modify the MainWindow class to use the ClientHandler in a separate thread.

Main Window Implementation
Header File: MainWindow.h

Make sure to include the ClientHandler header, and add the necessary includes for threading:

 

cpp

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QThread>
#include <QLabel>
#include <QVBoxLayout>
#include <QList>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void onNewConnection();

private:
    void setupUI();
    
    QTcpServer *tcpServer;
    QLabel *statusLabel;
    QList<QTcpSocket*> clientSockets;
};

cpp

Source File: MainWindow.cpp

Here’s the updated implementation of the MainWindow class to use threads for each new connection:

 

cpp

#include "mainwindow.h"
#include "ClientHandler.h"
#include <QThread>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), tcpServer(new QTcpServer(this))
{
    setupUI();

    // Start the TCP server on port 1234
    if (!tcpServer->listen(QHostAddress::Any, 1234)) {
        statusLabel->setText("Server failed to start.");
    } else {
        statusLabel->setText("Server listening on port 1234");
    }

    // Connect the newConnection signal from the server to the slot
    connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::onNewConnection);
}

MainWindow::~MainWindow()
{
    // Close all connections when shutting down
    foreach(QTcpSocket* socket, clientSockets) {
        if (socket) {
            socket->close();
            socket->deleteLater();
        }
    }
}

void MainWindow::setupUI()
{
    QWidget *centralWidget = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout;

    statusLabel = new QLabel("Server not started", this);
    layout->addWidget(statusLabel);

    centralWidget->setLayout(layout);
    setCentralWidget(centralWidget);
}

void MainWindow::onNewConnection()
{
    // Accept new connection
    QTcpSocket *clientSocket = tcpServer->nextPendingConnection();

    // Use a new thread to handle this connection
    QThread *thread = QThread::create([clientSocket]() {
        ClientHandler handler(clientSocket->socketDescriptor());
        handler.process();  // Call process in the thread
    });

    // Move the thread to the event loop and disconnect it on finish
    connect(thread, &QThread::finished, thread, &QObject::deleteLater);
    connect(clientSocket, &QTcpSocket::disconnected, thread, &QThread::quit);
    
    // Start the thread
    thread->start();
    
    // Add the new socket to the list of connected clients
    clientSockets.append(clientSocket);
    statusLabel->setText("New client connected!");
}

cpp

Explanation

  1. ClientHandler Class:

    • Implements handling for the TCP connection, including reading data and handling disconnections.
    • Managed by the MainWindow class through QTcpSocket.
  2. MainWindow Class:

    • On a new connection, creates a new QThread for the corresponding ClientHandler.
    • Ensures that when the socket is disconnected, the thread cleans itself up properly.
  3. Thread Management:

    • Each ClientHandler instance runs in its own thread, enabling simultaneous handling of multiple clients.

Note

Make sure you have the necessary QT += network in your .pro file to link against the Qt Network module. With these changes, every new client connection to your server will be handled on a separate thread, allowing your server to manage multiple clients concurrently.


原文地址:https://blog.csdn.net/m0_68739984/article/details/142463993

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!