采用重写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是否析构