QTcpServer多线程资源释放

采用重写QThread而非moveToThread的方法,难点在于资源的释放.因为一个socket对应一个thread,所以可以利用    socket断开或错误->删除socket->线程exit(0)的方式

TcpServer.cpp

#include "tcpserver.h"
#include "tcpthread.h"
#include "../mainwindow.h"
#include <QDebug>

TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
{
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
}

void TcpServer::startServer()
{
    if(!this->listen(QHostAddress(MainWindow::ip_combo_text),MainWindow::port_spin_num))
    {
        qDebug()<<"server can not listen!";
    }
    this->setMaxPendingConnections(maxThreadNum);
}

void TcpServer::stopServer()
{
    //clear thread
    emit sig_disconnect_socket();
    //_threadVec.clear();
    //stop server
    this->close();
}

void TcpServer::incomingConnection(qintptr handle)
{
    //校验线程数量,保证当前线程数小于最大线程数
    if(_threadVec.count()>=maxThreadNum)
    {
        return;
    }
    TcpThread *thread=new TcpThread(handle,this);
    _threadVec.append(thread);
    connect(thread,&TcpThread::finished,thread,&TcpThread::deleteLater);
    //用于close server时清空socket,然后socket线程清空线程
    connect(thread,&TcpThread::sig_socket_inited,[&,thread](){
        connect(this,&TcpServer::sig_disconnect_socket,thread->socket,&TcpSocket::disconnectFromHost,Qt::QueuedConnection);
    });
    thread->start();
}

TcpThread.cpp

#include "tcpthread.h"
#include <QDebug>
#include "tool/helper.h"

TcpThread::TcpThread(qintptr handle, QObject *parent) : QThread(parent)
{
    _handle=handle;
}

TcpThread::~TcpThread()
{
    qDebug()<<"TcpThread::~TcpThread()";
}

void TcpThread::run()
{
    socket=new TcpSocket;
    if(!socket->setSocketDescriptor(_handle))
    {
        qDebug()<<socket->errorString();
        return;
    }
    emit sig_socket_inited();
    _ip=socket->peerName();
    _port=socket->peerPort();
    connect(socket,&TcpSocket::readyRead,this,&TcpThread::handleReadyRead,Qt::DirectConnection);
    connect(socket,&TcpSocket::disconnected,this,&TcpThread::handleDisconnected,Qt::DirectConnection);
    connect(socket,static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),this,&TcpThread::handleSocketError,Qt::DirectConnection);
    exec();
}

void TcpThread::handleReadyRead()
{
    while(!socket->atEnd())
    {
            readBuf=socket->readAll();
            readDB+=readBuf;
    }
    Helper::isZhenOK(readDB);
}

void TcpThread::handleDisconnected()
{
    qDebug()<<"disconnected"<<_port;
    //disconnect之后,delete之前可能会有error,两者操作上有重复,所以要删掉一个
    disconnect(socket,static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),this,&TcpThread::handleSocketError);
    socket->deleteLater();
    socket=NULL;
    exit(0);
}

void TcpThread::handleSocketError(QAbstractSocket::SocketError error)
{
    qDebug()<<"socketerror"<<_port;
    //出现error之后,delete之前会disconnect,两者操作上有重复,所以要删掉一个
    disconnect(socket,&TcpSocket::disconnected,this,&TcpThread::handleDisconnected);
    socket->deleteLater();
    socket=NULL;
    exit(0);
}

MainWindow.cpp

connect(qApp,&QApplication::aboutToQuit,server,&TcpServer::stopServer);

可以重写析构函数,看thread和socket是否析构

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值