0
votes

I have a multiserverapp that works fine so far. I got 4 cpp files. Main.cpp constructs the program. MainWindow.cpp constructs the ui and starts (via buttonclick) MyServer.cpp. MyServer.cpp creates a thread and starts MyThread.cpp. My aim is to show several major steps (like the "server started", "new connection", etc..) on a textBrowser.

I pass the outputs from MyServer.cpp via emit updateUI("server started"); to mainwindow.cpp where the output gets catched by:

    //Mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myserver.h"
#include "mythread.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::AppendToBrowser(const QString text)
{
    ui->textBrowser->append(text);
}

void MainWindow::on_startButton_clicked()
{
    MyServer* mServer = new MyServer;
    connect(mServer, SIGNAL(updateUI(const QString)), this, SLOT(AppendToBrowser(const QString)));
    mServer->StartServer();

    ui->textBrowser->setPlainText("Server Started");
}

That works just right because the connect command is just in the mainwindow.cpp itself. The problem starts one step "deeper" in the mythread.cpp.

I created another signal in the

//MyThread.h

signals:
    void updateUI_serv(const QString text);

and connected it in the MyServer.cpp with the MainWindow.cpp.

    //MyServer.cpp

#include "myserver.h"
#include "mainwindow.h"

MyServer::MyServer(QObject *parent) :
    QTcpServer(parent)
{
}

void MyServer::StartServer()
{
    if(!this->listen(QHostAddress::Any,1234))
    {
        qDebug("Server Error");
    }
    else
    {
        qDebug("Server started");
    }
}

void MyServer::incomingConnection(int socketDescriptor)
{
    qDebug("new connection");


    MyThread *thread = new MyThread(socketDescriptor,this);
    MainWindow *mMain = new MainWindow;
    connect(thread, SIGNAL(updateUI_serv(const QString)),mMain ,SLOT(AppendToBrowser(const QString)));


    //flags thread for selfdeletion
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));



    //calls run
    thread->start();

    emit updateUI("thread started!");
}

// MyThread.cpp

#include "mythread.h"
#include "mainwindow.h"
#include "myserver.h"

MyThread::MyThread(int ID, QObject *parent) :
    QThread(parent)
{
    this->socketDescriptor = ID;
    emit updateUI_serv("start");
}

void MyThread::run()
{
    //thread stars here
    qDebug("Starting thread");
    socket = new QTcpSocket();
    emit updateUI_serv("hallo");
    //set socketdescriptor number
    if(!socket->setSocketDescriptor(this->socketDescriptor))
    {
        emit error(socket->error());
        return;
    }

    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::DirectConnection);


    qDebug("client connected");

    exec();
}

void MyThread::readyRead()
{
    QByteArray Data = socket->readAll();
    QString Datain = QString::fromLatin1(Data);
    qDebug("Date in:");

    emit updateUI_serv("data in:");
    socket->write(Data);
}

void MyThread::disconnected()
{
    qDebug("Disconnected");
    socket->deleteLater();
    exit(0);
}

The connect command lays here "in between" the signal (updateUI_serv from mythread.cpp) and the slot (AppendToBrowser from mainwindow.cpp) file. At this point the program crashes as soon as I try to write data (as a client via telnet) to the serverapp.

I tried to set the connect command into the mainwindow and the mythread as well, but both times I get different problems (like debugging problems, or the text does just not show up in the textBrowser). Thanks so far.

2
The program structure doesn't look very clear. MainWindow creates MyServer. Then MyServer creates another MainWindow. Which might create another MyServer, and so on. How many MainWindows do you have?user362638
now u see almost the full code. i know its not nice to do so, but i have no clue where to look for problems :(beary
Why do you create another MainWindow instance in the MyServer::incomingConnection? Are you aware that the mMain is completely different instance of MainWindow than the instance that created the MyServer instance in the first place.user362638

2 Answers

0
votes

Eventually the myServer-Object is not running in the MainThread, therefor accessing an ui element from another thread crashes your app.

You can make sure only Messages from mainThread will get displayed by adding the following code to your AppendToBrowser Slot:

if( QApplication::instance()->thread() == QThread::currentThread() )
    ui->textBrowser->setPlainText("whateverTextThereShallBe");
else
    return;
    //You should not run into this else...

This if section checks if the current object calling the update is the mainThread. The else-section checks for erros. If you are running in the else-section you are trying to change ui-elements form a thread which is not the mainThread (UI-Thread). Connect your SIGNAL in server to another SIGNAL (SIGNAL->SIGNAL connection) and add a connect to SIGNAL(SERVER) -> SLOT(MainWindow) in your MainWindow.cpp. Eventually try your connect-call with the 5th. parameter for Queued Connection (Qt::QueuedConnection IIRC).

0
votes

Ahh i got it on my own. I solved the problem by creating a NEW function ( void forwarding(const Qstring); ) and in that function i emitted it with the ordinary emit updateUI(text); .. stuff works finaly!