Qt 多线程TCP服务端一键关闭所有客户端
任务描述: 实现多线程TCP服务端一键关闭所有客户端的连接。
解决过程: 1、Qt的服务端提供了close的功能,但是只用来不响应新接入的客户端。
手册中是这样描述的:
void QTcpServer::close()
Closes the server. The server will no longer listen for incoming connections.
2、既然是多线程的服务端,每个客户端对应一个线程,那么将所有的线程都退出或者终止不就可以实现关闭所有的客户端了。
代码实现过程:
1、创建 threadList 成员用来管理线程
QList<serverThread *>threadlist;
2、修改incomingConnection()函数如下,对每一个客户端创建一个线程,同时将线程的指针地址添加threadlist中.
void MyTcpServer::incomingConnection(int sockDesc)
{
threadCount++;
m_socketList.append(sockDesc);
thread = new serverThread(sockDesc);
threadlist.append(thread);
//显示连接数
connect(thread, SIGNAL(connectTCP(int,QString )), m_Widget, SLOT(showConCont(int,QString)));
//显示客户端IP
connect(thread, SIGNAL(connectTCP(int,QString )), m_Widget, SLOT(showConnection(int,QString)));
connect(thread, SIGNAL(disconnectTCP(int,QString)), m_Widget, SLOT(showDisconnection(int,QString)));
connect(thread, SIGNAL(disconnectTCP(int,QString)), this, SLOT(disconnect(int,QString)));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
//接收数据
connect(thread, SIGNAL(dataReady(const QString&, const QByteArray&)),
m_Widget, SLOT(recvData(const QString&, const QByteArray&)));
//发送数据d
connect(m_Widget, SIGNAL(sendData(int,QString, const QByteArray&)),
thread, SLOT(sendDataSlot(int,QString, const QByteArray&)));
thread->start();
}
2、实现信号槽函数,实现关闭所有线程。在调试的过程中发现,如果delete thread[i],可能会导致程序出错。
注意到 connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 当线程终止的时候,自动会清理内存,所以不需要手动清理。为了避免列表对象只增不减,所以每当服务端关闭的时候,同时也清理线程列表。
void MyTcpServer:: disconnectAll()
{
for(int i = 0;i<threadlist.length();i++)
{
if(threadlist[i]->isRunning())
{
threadlist[i]->quit();
threadlist[i]->wait();
qDebug()<<i;
//delete threadlist[i]; //清理对象
}
else
{
qDebug()<<"thread i is not runnint!";
}
}
threadlist.clear(); //清理线程列表
}
3、主窗口点击断开链接后,发送断开所有连接的信号,所以需要将此信号与信号槽disconnectAll()关联。
connect(this, SIGNAL(disconnectAllClients()), m_server, SLOT(disconnectAll()));
4、最后完善主界面的uI的显示部分
severDisc = true;
emit disconnectAllClients();
ui->comboBox_ClientIP->clear();
ui->pushButton_Listen->setText("侦听");
ui->statusbar->showMessage("服务端关闭所有的连接!");
m_server->close(); //服务器将不再监听新接入的客户端
这样就完成了。