Qt 多线程TCP服务端一键关闭所有客户端

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();    //服务器将不再监听新接入的客户端

这样就完成了。
在这里插入图片描述

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是Qt多线程TCP服务端的实现示例: 1. 创建一个Qt控制台应用程序。 2. 在项目中添加一个新的类来实现TCP服务器。我们将称之为"TcpServer"。 3. 在TcpServer类的头文件中,添加以下内容: ``` #ifndef TCPSERVER_H #define TCPSERVER_H #include <QObject> #include <QTcpServer> #include <QTcpSocket> #include <QThread> class TcpServer : public QObject { Q_OBJECT public: explicit TcpServer(QObject *parent = nullptr); public slots: void newConnection(); //处理新连接 void readData(); //读取数据 void socketDisconnected(); //处理断开连接 private: QTcpServer *m_server = nullptr; //TCP服务器 QList<QTcpSocket*> m_sockets; //已连接TCP套接字 }; #endif // TCPSERVER_H ``` 4. 在TcpServer类的源文件中,实现以下内容: ``` #include "tcpserver.h" TcpServer::TcpServer(QObject *parent) : QObject(parent) { m_server = new QTcpServer(this); connect(m_server, &QTcpServer::newConnection, this, &TcpServer::newConnection); if (!m_server->listen(QHostAddress::Any, 1234)) { qWarning() << "Could not start server"; } else { qDebug() << "Listening on port 1234..."; } } void TcpServer::newConnection() { QTcpSocket *socket = m_server->nextPendingConnection(); connect(socket, &QTcpSocket::readyRead, this, &TcpServer::readData); connect(socket, &QTcpSocket::disconnected, this, &TcpServer::socketDisconnected); m_sockets.append(socket); } void TcpServer::readData() { QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender()); if (!socket) { return; } QByteArray data = socket->readAll(); qDebug() << "Received data:" << data; //将数据发送回客户端 socket->write(data); } void TcpServer::socketDisconnected() { QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender()); if (!socket) { return; } m_sockets.removeOne(socket); socket->deleteLater(); } ``` 5. 在main.cpp文件中,实例化TcpServer类并将其移动到一个新的线程中: ``` #include <QCoreApplication> #include <QThread> #include "tcpserver.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); //创建TcpServer对象 TcpServer *server = new TcpServer(); //创建新线程并将服务器对象移动到该线程 QThread *thread = new QThread(); server->moveToThread(thread); thread->start(); return a.exec(); } ``` 这样,我们就创建了一个基本的Qt多线程TCP服务端。当客户端连接服务器时,服务器将打印出"Listening on port 1234..."。当客户端发送数据时,服务器将打印出接收到的数据并将其发送回客户端。当客户端断开连接时,服务器将从已连接的套接字列表中删除该套接字。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值