Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

GUI of Fortune server example with multithreading in Qt 6



  • I am implementing a fortune server example with multi threading. I have used this example "https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html" and I want to make a UI for. It's working fine but the server is not sending the message to the client . I am sending the message like this in dthread.cpp file

    QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_6_0);
        out << text;
    
        tcpSocket->write(block);
    

    and It's not even reading the message that the client is sending. Can anyone tell me what is the issue. I have attached my whole code below.

    server-app.pro:

    QT       += core gui
    QT += network widgets
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    CONFIG += c++11
    
    # You can make your code fail to compile if it uses deprecated APIs.
    # In order to do so, uncomment the following line.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
        main.cpp \
        mainwindow.cpp\
        fthread.cpp \
        fserver.cpp
    
    HEADERS += \
        mainwindow.h\
        fthread.h \
        fserver.h
    
    
    FORMS += \
        mainwindow.ui
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
    

    fserver.h

    #ifndef FSERVER_H
    #define FSERVER_H
    #include <QStringList>
    #include <QTcpServer>
    class fserver : public QTcpServer
    {
        Q_OBJECT
    
    public:
        fserver(QObject *parent = nullptr);
    
    protected:
        void incomingConnection(qintptr socketDescriptor) override;
    
    private:
        QStringList fortunes;
    
    };
    //! [0]
    #endif // FSERVER_H
    
    

    fthread.h

    #ifndef FTHREAD_H
    #define FTHREAD_H
    #include <QThread>
    #include <QTcpSocket>
    #include <QTcpServer>
    //! [0]
    class fthread : public QThread
    {
        Q_OBJECT
    
    public:
    
        fthread(int socketDescriptor, const QString &fortune, QObject *parent);
        fthread(QObject *pwgt);
        QTcpServer *tcpServer;
        void run() override;
    
    
    signals:
        void error(QTcpSocket::SocketError socketError);
        void gotNewMesssage(QString msg);
    public slots:
        void readyRead();
    
    private:
        int socketDescriptor;
        QString text="mesage from server";
        QTcpSocket *tcpSocket;
    
    };
    //! [0]
    #endif // FTHREAD_H
    
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include "fserver.h"
    #include "fthread.h"
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
    
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    private slots:
        void on_connect_clicked();
       void gotNewMesssage(QString msg);
    
    
    private:
        Ui::MainWindow *ui;
        fserver server;
        fthread *threadobj;
    
    
    
    };
    #endif // MAINWINDOW_H
    
    

    fserver.cpp

    #include "fserver.h"
    #include "fthread.h"
    
    #include <QRandomGenerator>
    
    #include <stdlib.h>
    
    //! [0]
    fserver::fserver(QObject *parent)
        : QTcpServer(parent)
    {
        fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
                     << tr("You've got to think about tomorrow.")
                     << tr("You will be surprised by a loud noise.")
                     << tr("You will feel hungry again in another hour.")
                     << tr("You might have mail.")
                     << tr("You cannot kill time without injuring eternity.")
                     << tr("Computers are not intelligent. They only think they are.");
    
    }
    //! [0]
    
    //! [1]
    void fserver::incomingConnection(qintptr socketDescriptor)
    {
    
        QString fortune = fortunes.at(QRandomGenerator::global()->bounded(fortunes.size()));
        fthread *thread = new fthread(socketDescriptor,fortune, this);
        connect(thread, &fthread::finished, thread, &fthread::deleteLater);
        thread->start();
    }
    
    

    fthread.cpp

    #include "fthread.h"
    
    #include <QtNetwork>
    fthread::fthread(int socketDescriptor, const QString &fortune, QObject *parent)
        : QThread(parent), socketDescriptor(socketDescriptor), text(fortune)
    {
    }
    fthread::fthread(QObject *pwgt) : QThread(pwgt)
    {
    
    }
    void fthread::run()
    {
    
    
        tcpSocket = new QTcpSocket();
        if (!tcpSocket->setSocketDescriptor(socketDescriptor)) {
            emit error(tcpSocket->error());
            return;
        }
    
        connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
    
        tcpSocket->disconnectFromHost();
        tcpSocket->waitForDisconnected();
    }
    void fthread::readyRead()
    {
        // get the information
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_6_0);
        out << text;
    
        tcpSocket->write(block);
    
            QByteArray Data = tcpSocket->readAll();
    
            // will write on server side window
            qDebug() << socketDescriptor << " Data in: " << Data;
            QString str;
            str="hello world";
            emit gotNewMesssage(str);
    
    
    }
    
    
    
    

    mainwindow.cpp

    #include <stdlib.h>
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "fserver.h"
    #include "fthread.h"
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        /*threadobj= new fthread();
        connect(threadobj, &fthread::gotNewMesssage,
                this, &MainWindow::gotNewMesssage);*/
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_connect_clicked()
    {
        if (!server.listen(QHostAddress::Any, 54000)) {
            ui->textlog->append("unable to start the server");
            close();
            return;
        }
    
        ui->textlog->append("The server is listening\n");
    
    
        //connect(quitButton, &QPushButton::clicked, this, &Dialog::close);
    
    }
    
    
    

    main.cpp

    #include "mainwindow.h"
    
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    
    

  • Lifetime Qt Champion

    First question: why on hell do you think you need threads here?

    Second:

    void fserver::incomingConnection(qintptr socketDescriptor)
    {

    fthread *thread = new fthread();
    connect(thread, &fthread::finished, thread, &fthread::deleteLater);
    thread->start();
    

    }

    Where do you initialize fthread::tcpServer (whyever this is needed) and fthread::socketDescriptor



  • @Christian-Ehrlicher It is my assignment and I need to do multi threading here. Also, I've edited my code after initializing socketdescriptor


  • Lifetime Qt Champion

    @fari35 said in GUI of Fortune server example with multithreading in Qt 6:

    tcpSocket->disconnectFromHost();
    tcpSocket->waitForDisconnected();
    

    You know what they're doing? How do you expect that you receive something when you immediately close the socket?



  • @Christian-Ehrlicher I've first connected it to the readyread() funtion in fthread.h class.

    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
    
        tcpSocket->disconnectFromHost();
        tcpSocket->waitForDisconnected();
    

  • Lifetime Qt Champion

    @fari35 said in GUI of Fortune server example with multithreading in Qt 6:

    I've first connected it to the readyread() funtion in fthread.h class.

    And then you directly close the socket... so again - why do you think you should receive something.

    Please read the documentation when you want to use a QThread (you use the second option).



  • It is very hard for an individual (or a group) to debug your whole program (its design and its implementation) via a forum. This is not likely to succeed, in my opinion.

    To have success in a Q&A forum, the problem statement needs to be minimized.

    In your case, @fari35 , I would highly recommend that you start by only compiling and running the exact "untouched" sample code first:

    Also compiling and run the exact unedited official client sample:

    Make sure all of that works first. I was able to compile and launch both of those with no issue, and this is what I see:
    Screenshot from 2020-12-21 09-30-19.png

    Once you do that, then start tracking your changes using git, and make one tiny change a time (in order to work slowly towards whatever your goal or assignment is).

    When you make one tiny change (as small as editing or adding just one line of code) and the change fails to do what you expect, then you can use the time-tested bug-reporting technique of:

    1. State what you did (the single tiny change).
    2. State what you expected.
    3. State what actually happened.

Log in to reply