Crash of the Server Application



  • Hi,

    When I connect with the Server Application I receive the Crash Error on the line:

    @if( !socket->setSocketDescriptor( m_descriptor ) )@

    Please, run the project "ServerTimer" than run "ViewerServerTimer" and click the button "Connect"

    ServerTime.pro
    @
    QT += core
    QT += network
    QT -= gui

    TARGET = ServerTimer
    CONFIG += console
    CONFIG -= app_bundle

    TEMPLATE = app

    SOURCES += main.cpp
    server.cpp
    serverthread.cpp

    HEADERS +=
    server.h
    serverthread.h
    @

    main.cpp
    @
    #include <QCoreApplication>
    #include "server.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    Server server;
    if( !server.listen( QHostAddress::Any, 1234 ) )
    {
        qCritical( "Cannot listen to port 1234." );
        return 1;
    }
    
    return a.exec&#40;&#41;;
    

    }
    @

    server.h
    @
    #ifndef SERVER_H
    #define SERVER_H

    #include <QTcpServer>
    #include "serverthread.h"

    class Server : public QTcpServer
    {
    public:
    Server();

    protected:
    void incomingConnection(int descriptor);

    private:
    ServerThread *thread;
    };

    #endif // SERVER_H
    @

    server.cpp
    @
    #include "server.h"

    Server::Server() : QTcpServer()
    {
    }

    void Server::incomingConnection( int descriptor )
    {
    thread = new ServerThread( descriptor, this );

    connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater()) );
    thread->start();
    

    }
    @

    serverthread.h
    @
    #ifndef SERVERTHREAD_H
    #define SERVERTHREAD_H

    #include <QThread>
    #include <QTimer>
    #include <QTcpSocket>

    class ServerThread : public QThread
    {
    public:
    ServerThread( int descriptor, QObject *parent );

    void run();
    

    public slots:
    void sendData();

    private:
    int m_descriptor;

    private:
    QTimer *timer;
    QTcpSocket *socket;
    };

    #endif // SERVERTHREAD_H
    @

    serverthread.cpp
    @
    #include "serverthread.h"

    ServerThread::ServerThread( int descriptor, QObject *parent ) : QThread( parent )
    {
    m_descriptor = descriptor;
    }

    void ServerThread::run()
    {
    if( !socket->setSocketDescriptor( m_descriptor ) )
    {
    qDebug( "Socket error!" );
    return;
    }

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(sendData()));
    timer->start(1000);
    

    }

    void ServerThread::sendData() {
    //socket->write( "data" );
    }
    @

    ViewerServerTimer.pro
    @
    SOURCES +=
    main.cpp
    timerdialog.cpp

    HEADERS +=
    timerdialog.h

    QT += network
    @

    main.cpp
    @
    #include <QApplication>
    #include "timerdialog.h"

    int main( int argc, char **argv )
    {
    QApplication app( argc, argv );

    TimerDialog win;
    //win.resize(500, 500);
    win.show();
    
    return app.exec();
    

    }
    @

    timerdialog.h
    @
    #ifndef TIMERDIALOG_H
    #define TIMERDIALOG_H

    #include <QDialog>
    #include <QTcpSocket>
    #include <QtGui>

    class TimerDialog : public QDialog
    {
    Q_OBJECT
    public:
    explicit TimerDialog(QWidget *parent = 0);

    signals:

    public slots:
    void on_btnConnect_clicked();
    void readyRead();
    void error(QAbstractSocket::SocketError error);

    private:
    QTcpSocket *socket;
    QLineEdit *leHostName;
    QSpinBox *sbPort;
    QPushButton *btnConnect;
    QLineEdit *leTimer;
    };

    #endif // TIMERDIALOG_H
    @

    timerdialog.cpp
    @
    #include "timerdialog.h"

    TimerDialog::TimerDialog(QWidget *parent) :
    QDialog(parent)
    {
    // Connecting
    QLabel *lblHostName = new QLabel(tr("Host Name:"));
    leHostName = new QLineEdit("localhost");

    QLabel *lblPort = new QLabel(tr("Port:"));
    sbPort = new QSpinBox;
    sbPort->setMaximum(9999);
    sbPort->setValue(1234);
    
    btnConnect = new QPushButton(tr("Connect"));
    
    QGridLayout *connectLayout = new QGridLayout;
    connectLayout->addWidget(lblHostName, 0, 0);
    connectLayout->addWidget(leHostName, 0, 1);
    connectLayout->addWidget(lblPort, 1, 0);
    connectLayout->addWidget(sbPort, 1, 1);
    connectLayout->addWidget(btnConnect, 2, 0, 1, 2);
    
    QGroupBox *connectGroupBox = new QGroupBox;
    connectGroupBox->setTitle(tr("Connecting"));
    connectGroupBox->setLayout(connectLayout);
    
    // Timer
    QLabel *lblTimer = new QLabel(tr("Timer:"));
    leTimer = new QLineEdit("");
    leTimer->setReadOnly(true);
    
    QHBoxLayout *timerLayout = new QHBoxLayout;
    timerLayout->addWidget(lblTimer);
    timerLayout->addWidget(leTimer);
    
    QGroupBox *timerGroupBox = new QGroupBox;
    timerGroupBox->setTitle(tr("Output From Server"));
    timerGroupBox->setLayout(timerLayout);
    
    // MainLaoyt
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(connectGroupBox);
    mainLayout->addWidget(timerGroupBox);
    
    this->setLayout(mainLayout);
    
    socket = new QTcpSocket;
    
    connect(btnConnect, SIGNAL(clicked()), this, SLOT(on_btnConnect_clicked()));
    
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
    

    }

    void TimerDialog::on_btnConnect_clicked() {
    socket->connectToHost(leHostName->text(), sbPort->value());

    btnConnect->setEnabled(false);
    

    }

    void TimerDialog::readyRead() {
    QString time;
    time = socket->read(256);
    leTimer->setText(time);
    }

    void TimerDialog::error(QAbstractSocket::SocketError error) {
    if( error == QAbstractSocket::RemoteHostClosedError )
    return;

    QMessageBox::warning(this, tr("Error"), tr("TCP error: %1").arg( socket->errorString()));
    btnConnect->setEnabled(true);
    

    }
    @

    Thank you!


  • Lifetime Qt Champion

    Hi,

    Did you run your program through a debugger ?

    Did you check that you initialize all your variables ?



  • Thank you for reply :)

    Yes, I did it.

    The program crashed on the line:

    @if( !socket->setSocketDescriptor( m_descriptor ) )@

    the variable m_descriptor is initialized in constructor. It's very simple application but I don't know where my mistake. Please, help me. It is very important for me :(


  • Lifetime Qt Champion

    And what about socket ?



  • Thank you. I wrote:

    @
    void ServerThread::run()
    {
    socket = new QTcpSocket;
    ...
    }
    @

    But now output is:
    @QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QThread(0x547258), parent's thread is QThread(0x5416a8), current thre
    ad is QThread(0x547258)
    Object::connect: No such slot QThread::sendData() in ../ServerTimer/serverthread
    .cpp:20@



  • "You're doing it wrong":http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/ . That's what happens if people subclass QThread without knowing about the implications this has.

    The socket variable is a member of your QThread subclass. The instance of your QThread subclass lives in the context of the main thread, so the instance of the member variable socket also lives in the main thread. But everything that happens inside the run method of your QThread subclass happens in the context of the new thread. So when you try to asign to the socket member var from inside the run() function you get the "QObject: Cannot create children for a parent that is in a different thread." output.

    Consider using "the worker object approach":http://qt-project.org/wiki/QThreads_general_usage .



  • Thank you. I'll read about threads.

    Why when I comment the timer does the program works?

    @
    #include "serverthread.h"

    ServerThread::ServerThread( int descriptor, QObject *parent ) : QThread( parent )
    {
    m_descriptor = descriptor;
    }

    void ServerThread::run()
    {
    socket = new QTcpSocket;

    if( !socket->setSocketDescriptor( m_descriptor ) )
    {
        emit error(socket->error());
        return;
    }
    

    // timer = new QTimer(this);
    // connect(timer, SIGNAL(timeout()), this, SLOT(sendData()));
    // timer->start(1000);

    qDebug() << m_descriptor << " Client Connected";
    
    exec&#40;&#41;;
    

    }

    void ServerThread::sendData() {
    //socket->write( "time" );
    }
    @

    I want to use a timer in my thread.


  • Lifetime Qt Champion

    What do you mean by "works" ?



  • [quote author="SGaist" date="1378153105"]What do you mean by "works" ?[/quote]

    I don't see the message:
    @
    Listening...
    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is ServerThread(0x3d7258), parent's thread is QThread(0x3d16a8), current
    thread is ServerThread(0x3d7258)
    272 Client Connected
    @

    Maybe is this right:

    @timer = new QTimer(0);@



  • No... When I ran my application I received from server the word "time" and the report:

    Listening...
    268 Client Connected
    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QNativeSocketEngine(0x1e1e430), parent's thread is ServerThread(0x627
    258), current thread is QThread(0x6216a8)
    QSocketNotifier: socket notifiers cannot be disabled from another thread
    ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects ow
    ned by a different thread. Current thread 6216a8. Receiver '' (of type 'QNativeS
    ocketEngine') was created in thread 627258", file kernel/qcoreapplication.cpp, l
    ine 535

    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information.
    Press <RETURN> to close this window...

    @#include "serverthread.h"

    ServerThread::ServerThread( int descriptor, QObject *parent ) : QThread( parent )
    {
    m_descriptor = descriptor;
    }

    void ServerThread::run()
    {
    socket = new QTcpSocket;

    if( !socket->setSocketDescriptor( m_descriptor ) )
    {
        emit error(socket->error());
        return;
    }
    
    timer = new QTimer(0);
    connect(timer, SIGNAL(timeout()), this, SLOT(sendData()));
    timer->start(1000);
    
    qDebug() << m_descriptor << " Client Connected";
    
    exec&#40;&#41;;
    

    }

    void ServerThread::sendData() {
    socket->write( "time" );
    }
    @


  • Lifetime Qt Champion

    Before going further and since you seem to be starting with network + threads... Are you sure you need threads ? (QTcpServer/Socket are asynchronous so you don't really need them). Did you take a look at the QtNetwork module examples ? (Thinking of the client/fortune example and the threaded version)



  • Thank you. I will have a many clients for my server. I'll see network examples from Qt SDK.



  • Take a look to this tutorial:
    "Advanced Asynchronous QTcpServer with QThreadPool":http://voidrealms.com/viewtutorial.aspx?id=39



  • [quote author="qxoz" date="1378183845"]Take a look to this tutorial:
    "Advanced Asynchronous QTcpServer with QThreadPool":http://voidrealms.com/viewtutorial.aspx?id=39
    [/quote]

    Thank you very much :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.