我的gui有一个两个按钮,一个启动服务器&另一个是停止服务器。
Brief
:---
启动服务器后,在每个新的客户端请求中,我将创建一个新的线程&这将处理与客户的沟通。
Detail
: -
当按下start button
时,我创建了一个对象“tcpserverobjectWrapper
”,它创建了另一个对象“tcpserverobject
”,此对象创建了一个Qtcpserver。
现在这个Qtcpserver列出了新的连接。当一个新连接到来时,我创建了一个“TcpSocketThreadWrapperObject
”对象
创造一个线程&此线程处理与客户端的通信。此外,“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 ..!!!
答案 0 :(得分:0)
我认为所有这一切的最简单的解决方案是停止使用QThread。
QTcpSocket和QTcpServer都是异步的,所以当你收到连接时,你只需要创建一个包装QTcpSocket的类,这个类处理数据的读取,将QTcpSocket信号连接到类的插槽。
如果你获得了很多连接,那么你将创建大量的线程。比处理器核心更多的线程只是浪费时间。
如果每个连接都请求服务器完成大量工作,那么您可以创建单独的工作对象并将它们移动到不同的线程,但总的来说,我建议您不要为QTcpServer和QTcpSockets使用单独的线程