mardi 21 juin 2016

How to create QTcpServer on a QThread and then stop it from the main thread

I have provided my entire code below. Please excuse the design as I am new to Qt and this is a quick and dirty example.

What I want to do is create a QThread that manages a QTcpServer listener. I want it to be able to close listener when stopped and then reopen it when started again. Please ignore the fact that the listener may be getting leaked right now, I will tackle that issue later.

I believe the problem is that when Stop is called it invokes the m_listener->close() method on a different thread (invoked from the main thread) than the thread it was created on (it was created on the TcpServerThread). So the questions is, how to I fix it? Or how to I redesign it so I avoid this issue?

This isn't the full design, I have made a toy example that mimicks the real thing.

tcpserverthread.h

#ifndef TCPSERVERTHREAD_H
#define TCPSERVERTHREAD_H

#include <QObject>
#include <QThread>

class QTcpServer;

class TcpServerThread : public QThread
{
    Q_OBJECT
public:
    TcpServerThread();

    void run();

    void Start();
    void Stop();
public slots:
    void newConnection();

private:

    QTcpServer* m_pListener;
};

#endif // TCPSERVERTHREAD_H

tcpserverthread.cpp

#include "tcpserverthread.h"
#include "tcpserver.h"
#include <iostream>
#include <QTcpServer>
#include <QTcpSocket>
#include <QCoreApplication>

TcpServerThread::TcpServerThread()
{

}

void TcpServerThread::run()
{
    std::cout << "thread started ..." << std::endl;
    std::cout << "listener starting ..." << std::endl;
    m_pListener = new QTcpServer();
    connect(m_pListener, SIGNAL(newConnection()), this, SLOT(newConnection()));
    if(!m_pListener->listen(QHostAddress::Any, 1234))
    {
        std::cout << "listener could NOT START - " << m_pListener->errorString().toStdString() << std::endl;
    }
    else
    {
        std::cout << "listener SUCCESSFULLY STARTED" << std::endl;
    }

//    std::cout << "thread running..." << std::endl;
//    m_pListener = new TcpServer();
//    m_pListener->Start();

    exec();
}

void TcpServerThread::newConnection()
{
    qDebug() << "in new conn ... ";
    //std::cout << "in new conn.." << std::endl;
    QTcpSocket *soc = m_pListener->nextPendingConnection();
    soc->write("hello client");
}

void TcpServerThread::Start()
{
    start();
}

void TcpServerThread::Stop()
{
    std::cout << "TcpServer Stopping . . . " << std::endl;
    //this close is the line that causes the problem... 
    m_pListener->close();
    this->quit();
}

main.cpp

#include <QCoreApplication>
#include <iostream>
#include <QTcpServer>
#include "tcpserver.h"

#include "tcpserverthread.h"

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

    TcpServerThread *t = new TcpServerThread();
    t->Start();
    t->Stop();

    return a.exec();
}

If you comment out the call to t->Stop in main you can then run it and use telnet (or putty) to connect to it @ 127.0.0.1:1234.

I want to make it so it can be stopped and then started again and connections will work.

Aucun commentaire:

Enregistrer un commentaire