參考:https://blog.csdn.net/qqwangfan/article/details/78271110
-
// qtcpserver使用多線程處理連進來的qtcpsocket端
-
//頭文件
-
-
-
-
-
// tcpsocket從qtcpsocket繼承下來,需要將tcpsocket移到線程里使用,故tcpsocket需處理的都放進槽里,使用信號發射后,槽函數就在線程里運行
-
// tcpserver從QTcpServer繼承下來,重載incomingConnection函數
-
-
class TcpSocket : public QTcpSocket
-
{
-
Q_OBJECT
-
public:
-
TcpSocket( int socketdesc,QTcpSocket *parent = NULL);
-
~TcpSocket();
-
-
private slots:
-
void ReadAndParseData();
-
void SocketErr(QAbstractSocket::SocketError socketError);
-
private:
-
QString m_recvDataStr;
-
};
-
-
class TcpServer : public QTcpServer
-
{
-
Q_OBJECT
-
public:
-
TcpServer( const std:: string &ip, int port, QTcpServer *parent = NULL);
-
~TcpServer();
-
-
protected:
-
void incomingConnection(qintptr socketDescriptor);
-
-
private slots:
-
void SocketDisconn();
-
-
private:
-
QList<TcpSocket*> m_socketList;
-
};
-
-
-
//cpp文件
-
-
-
-
-
-
TcpSocket::TcpSocket( int sock, QTcpSocket *parent) : QTcpSocket(parent)
-
{
-
this->setSocketDescriptor(sock);
-
connect( this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SocketErr(QAbstractSocket::SocketError)));
-
}
-
-
TcpSocket::~TcpSocket()
-
{
-
-
}
-
-
// 將會移進線程里面運行
-
void TcpSocket::ReadAndParseData()
-
{
-
TcpSocket *socket = (TcpSocket*)sender();
-
QString recvStr = socket->readAll();
-
m_recvDataStr += recvStr;
-
// 對數據的處理
-
}
-
-
void TcpSocket::SocketErr(QAbstractSocket::SocketError socketError)
-
{
-
TcpSocket *socket = (TcpSocket*)sender();
-
WLog(LOG_ERR, "socket[%d] ip[%s] port[%d] err[%s]", socket->socketDescriptor(),
-
socket->peerAddress().toString().toLocal8Bit().data(),socket->peerPort(),socket->errorString().toLocal8Bit().data());
-
}
-
-
-
TcpServer::TcpServer( const std:: string &ip, int port, QTcpServer *parent) : QTcpServer(parent)
-
{
-
bool bsucc;
-
if (ip.empty())
-
{
-
bsucc = this->listen(QHostAddress::AnyIPv4, port);
-
}
-
else
-
{
-
bsucc = this->listen(QHostAddress(ip.c_str()), port);
-
}
-
-
WLog(LOG_INFO, "listen bsucc[%d],ip[%s] port[%d] errstr[%s]", bsucc,ip.c_str(),
-
port, this->errorString().toLocal8Bit().data());
-
}
-
-
TcpServer::~TcpServer()
-
{
-
this->close();
-
/*QList<TcpSocket*>::iterator it = m_socketList.begin();
-
for (; it != m_socketList.end(); )
-
{
-
TcpSocket* sock = *it;
-
it = m_socketList.erase(it);
-
delete sock;
-
sock = NULL;
-
}
-
m_socketList.clear();*/
-
}
-
-
/*
-
Note: If you want to handle an incoming connection as a new QTcpSocket object in another thread you have to
-
pass the socketDescriptor to the other thread and create the QTcpSocket object there and use its setSocketDescriptor() method.
-
*/
-
void TcpServer::incomingConnection(qintptr socketDescriptor)
-
{
-
TcpSocket *socket = new TcpSocket(socketDescriptor);
-
-
connect(socket, SIGNAL(readyRead()), socket, SLOT(ReadAndParseData())); // 會移進線程里
-
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
-
-
QThread *thread = new QThread(socket); // 以socket為父類,當socket釋放刪除后也會刪除線程,或者將線程的quit信號關聯槽deleteLater()也可以達到效果
-
connect(socket, SIGNAL(disconnected()), thread, SLOT(quit()));
-
socket->moveToThread(thread);
-
thread->start();
-
emit newConnection(); //文檔要求繼承本函數需要發射此信號,此處沒有與此信號連接的槽
-
}
-
-
void TcpServer::SocketDisconn()
-
{
-
/*TcpSocket* socket = (TcpSocket*)sender();
-
QList<TcpSocket*>::iterator it = find(m_socketList.begin(), m_socketList.end(), socket);
-
if (it != m_socketList.end())
-
{
-
m_socketList.erase(it);
-
delete socket;
-
socket = NULL;
-
}*/
-
}
在外部使用TcpServer *server = new TcpServer(ip,port);即可作為服務器監聽