QTcpServer - 如何停止客户端线程

时间:2013-11-21 15:37:32

标签: qt qtcpsocket qtcpserver

我的gui有一个两个按钮,一个启动服务器&另一个是停止服务器。

Brief:--- 启动服务器后,在每个新的客户端请求中,我将创建一个新的线程&这将处理与客户的沟通。

Detail: -
当按下start button时,我创建了一个对象“tcpserverobjectWrapper”,它创建了另一个对象“tcpserverobject”,此对象创建了一个Qtcpserver。 现在这个Qtcpserver列出了新的连接。当一个新连接到来时,我创建了一个“TcpSocketThreadWrapperObject”对象 创造一个线程&amp;此线程处理与客户端的通信。此外,“tcpserverobject”还会保留创建的新客户端请求对象列表 'QList<TcpSocketThreadWrapperObject *> TcpSocketThreadWrapperObjectList;'。

我可以从telnet客户端连接到服务器&amp;它为每个客户创建新线程&amp;工作良好。

stop button按下时,我可以停止服务器&amp;客户线程。

但我在这里two problems:--- 1 GT;每次客户端都会向服务器发送一些数据。我得到了这种QsocketNotifier。这是什么?

QSocketNotifier: socket notifiers cannot be enabled from another thread
QSocketNotifier: socket notifiers cannot be disabled from another thread

2 - ;如果我按下GUI上的停止按钮,我可以成功停止线程。

但是如何阻止线程&amp;当客户端向服务器发送“STOP command”或者向服务器发送closes the connection时,删除为每个客户端创建的对象?    我还必须删除在每个客户端请求中创建的以下对象?    客户请求 - &gt; TcpSocketThreadWrapperObject - 创建 - &gt; TcpSocketThreadObject - 创建 - &gt; TcpSocketThreadObject

有人可以建议如何解决上述两个问题吗?对此的答复将不胜感激。

这是代码:---

================= start&amp;停止按钮处理程序=====

void MainWindow::on_actionStop_triggered()
{
    if(b_threadAlreadyStarted)
    {

    /* ------------------ Tcp server object ------------------------*/

        b_threadAlreadyStarted = false;
        delete p_tcpserverobjectWrapper;

    /* ------------------ Tcp server object ------------------------*/

    }

}



void MainWindow::on_actionStart_triggered()
{

    if(!b_threadAlreadyStarted)
    {

    /* ------------------ Tcp server object ------------------------*/

        b_threadAlreadyStarted =true;

        p_tcpserverobjectWrapper = new tcpserverobjectWrapper(this,modelCANalyzer);

        qDebug() << " \n start ";

    /* ------------------ Tcp server object ------------------------*/

    }
}

======== tcpserverobjectWrapper class ===============

// Main server object wrapper
class tcpserverobjectWrapper : public QObject
{
    Q_OBJECT
public:
    explicit tcpserverobjectWrapper(QMainWindow *ptrWidget, QStandardItemModel *modelCANalyzer, QObject *parent=0);
    ~tcpserverobjectWrapper();

    //Device thread object
    tcpserverobject *m_tcpserverobject;
};



tcpserverobjectWrapper::tcpserverobjectWrapper(QMainWindow *ptrWidget , QStandardItemModel *modelCANalyzer,QObject *parent) :
    QObject(parent)
{
    m_tcpserverobject = new tcpserverobject ;

    //save model
    m_tcpserverobject->modeltable = modelCANalyzer;
    m_tcpserverobject->ptrmainwindow = ptrWidget;


    qDebug() << "\n tcp server thread started";

}

tcpserverobjectWrapper::~tcpserverobjectWrapper()
{

    qDebug() << " \n called delete later on tcpserverobjectWrapper .. !!";

    m_tcpserverobject->deleteLater();   // ---------------------> change it to - delete m_tcpserverobject

    qDebug() << " \n tcp server object successfully quited .. !! ";
}

========== tcpserverobject object ==================

class tcpserverobject : public QObject
{
    Q_OBJECT
public:
    explicit tcpserverobject(QObject *parent = 0);
    ~tcpserverobject();

    /*!
        Pointer to QStandardItemModel to be used inside - canTableView
    */
    QStandardItemModel *modeltable;

    //mainwindow pointer
    QMainWindow *ptrmainwindow;

    // Create list of new -- socket thread wrapper objects
    QList<TcpSocketThreadWrapperObject *> TcpSocketThreadWrapperObjectList;

private:
    QTcpServer *tcpServer;

signals:

public slots:

    void on_newConnection();

};

tcpserverobject::tcpserverobject(QObject *parent) :
    QObject(parent), tcpServer(0)
{
    tcpServer = new QTcpServer;

    // Connect slot of the server
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(on_newConnection()));

    //lisen on socket
    if (!tcpServer->listen(QHostAddress::LocalHost, SERVER_PORT )) {

        qDebug() << "\n returning from server listning error .. !!! ";

        return;
    }

    qDebug() << "\n server listning";

}

tcpserverobject::~tcpserverobject()
{

   // to do
    while (!TcpSocketThreadWrapperObjectList.isEmpty())
        delete TcpSocketThreadWrapperObjectList.takeFirst();
}

void tcpserverobject::on_newConnection()
{
    QByteArray block;

    block.append(" \n Hello from server .. !!!") ;

    QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
    connect(clientConnection, SIGNAL(disconnected()),
                clientConnection, SLOT(deleteLater()));

    // Create new thread for this .. client request ..!!
    qDebug() << "\n New connection request ..!!!";
    qDebug() << "\n New client from:" << clientConnection->peerAddress().toString();

    clientConnection->write(block);
    clientConnection->flush();

    // create new tcp object
    TcpSocketThreadWrapperObject* TcpSocketThreadWrapperObjectPtr = new TcpSocketThreadWrapperObject(clientConnection);

    // Append object to the list
    TcpSocketThreadWrapperObjectList.append(TcpSocketThreadWrapperObjectPtr);

}

============ TcpSocketThreadWrapperObject ==============

// Main device thread object
class TcpSocketThreadWrapperObject : public QObject
{
    Q_OBJECT
public:
    explicit TcpSocketThreadWrapperObject(QTcpSocket *m_pTcpSocket , QObject *parent = 0);
    ~TcpSocketThreadWrapperObject();

    /*!
        pointer for write thread
    */
    QThread m_TcpSocketRWThread;

    /// pointer to the socketthread  object
    class TcpSocketThreadObject *m_pTcpSocketThreadObject;


signals:

public slots:

};


// constructor for the deviceThreadObject
TcpSocketThreadWrapperObject::TcpSocketThreadWrapperObject(QTcpSocket *m_pTcpSocket , QObject *parent) :
    QObject(parent)
{
    m_pTcpSocketThreadObject = new TcpSocketThreadObject(m_pTcpSocket);

    //set flag for event loop -- make while(1)
    m_pTcpSocketThreadObject->m_bQuit = false;
    // connect the signal & slot
    connect(&m_TcpSocketRWThread,SIGNAL(started()),m_pTcpSocketThreadObject,SLOT(dowork_socket()));
    // Move thread to object
    m_pTcpSocketThreadObject->moveToThread(&m_TcpSocketRWThread);

    //Start the thread
    m_TcpSocketRWThread.start();

}

TcpSocketThreadWrapperObject::~TcpSocketThreadWrapperObject()
{

    //set flag for event loop -- make while(0)
    m_pTcpSocketThreadObject->m_bQuit = false;

    // Wait for the thread to terminate
    m_TcpSocketRWThread.quit();
    m_TcpSocketRWThread.wait();

    // Delete the object
    m_pTcpSocketThreadObject->deleteLater();

    qDebug() << "\n deleted - TcpSocketThreadWrapperObject";

}

======== TcpSocketThreadObject对象========

class TcpSocketThreadObject : public QObject
{
    Q_OBJECT
public:
    explicit TcpSocketThreadObject(QTcpSocket *m_pTcpSocketTemp , QObject *parent = 0);
    ~TcpSocketThreadObject();

    /*!
        Pointer to TCP socket -- created by the server
    */
    QTcpSocket *m_pclientConnectionSocket;


    /*!
      Termination control main thread
    */
    volatile  bool m_bQuit;

signals:

public slots:
    void dowork_socket();

};


// constructor for the deviceThreadObject
TcpSocketThreadObject::TcpSocketThreadObject(QTcpSocket *m_pTcpSocketTemp , QObject *parent) :
    QObject(parent)
{
    m_pclientConnectionSocket = m_pTcpSocketTemp;

    // todo
}

TcpSocketThreadObject::~TcpSocketThreadObject()
{
    // todo

}

void TcpSocketThreadObject::dowork_socket()
{
    QByteArray block;

    block.append(" \n hi again .. !!!") ;

    // Write to socket
    m_pclientConnectionSocket->write(block);
    m_pclientConnectionSocket->flush();

    // Close socket
    m_pclientConnectionSocket->disconnectFromHost();
    qDebug() << "\n entring loop of socket thread ..!!!";

    while(!m_bQuit)
    {
        // while loop --> send/rx command from client
    }

}

=======连接到服务器的一个客户端的输出=====

 New connection request ..!!! 

 New client from: "127.0.0.1" 
QSocketNotifier: socket notifiers cannot be enabled from another thread
QSocketNotifier: socket notifiers cannot be disabled from another thread

 entring loop of socket thread ..!!! 

1 个答案:

答案 0 :(得分:0)

我认为所有这一切的最简单的解决方案是停止使用QThread。

QTcpSocket和QTcpServer都是异步的,所以当你收到连接时,你只需要创建一个包装QTcpSocket的类,这个类处理数据的读取,将QTcpSocket信号连接到类的插槽。

如果你获得了很多连接,那么你将创建大量的线程。比处理器核心更多的线程只是浪费时间。

如果每个连接都请求服务器完成大量工作,那么您可以创建单独的工作对象并将它们移动到不同的线程,但总的来说,我建议您不要为QTcpServer和QTcpSockets使用单独的线程