QTcpServer使用多线程处理连接进来的QTcpSocket

// qtcpserver使用多线程处理连进来的qtcpsocket端
//头文件  
#pragma once
#include <qtcpserver.h>
#include <qtcpsocket.h>
#include <qmap.h>
// 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文件
#include <qthread.h>
#include <qlist.h>
#include "TcpServer.h"
#include "log.h"

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;
		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()), this, SLOT(SocketDisconn()));

	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);即可作为服务器监听

猜你喜欢

转载自blog.csdn.net/qqwangfan/article/details/78271110
今日推荐