0
点赞
收藏
分享

微信扫一扫

QT服务器

芷兮离离 2022-04-13 阅读 100
qtc++

使用QtQSignalMapper建立服务器多客户端处理

原因:

每当新建立一个连接时会发出一个newConnection()信号,在处理信号函数中调用nextPendingConnection()会建立一个新的通信Socket,但是多个客户端连接时,上以个Socket会被覆盖,如果使用QList储存所有客户端时,QList内的Socket无法及时通过readyRead()信号读取信息等问题,需要不断遍历QList的来获取信号,而且效率不高.

解决方案:

通过QSignalMapper与QList组合,将readyRead()信号全部绑定到QSignalMapper里面,在将Socket添加到QSignalMapper``中时建立与QList一直的索引,每次QSignalMapper发出'readyRead()`'信号时会同时发出索引值,从而取得当前通信的Socket

  1. 实现void incomingConnection(qintptr socketDescriptor)虚函数
//.h文件
#ifndef __REWRITETCPSERVER
#define __REWRITETCPSERVER
#include <QObject>
#include <QTcpServer>

class RewriteTcpServer : public QTcpServer{
	Q_OBJECT
protected:
	void incomingConnection(qintptr socketDescriptor);
signals:
	void sendSocket(qintptr ocketDescriptor);
public:
	RewriteTcpServer(QObject* parent);
	~RewriteTcpServer();
};
#endif //__REWRITETCPSERVER

//cpp文件
#include "RewriteTcpServer.h"
RewriteTcpServer::RewriteTcpServer(QObject* parent)
	: QTcpServer(parent) {
}
//重写tcpserver将套接字描述符转发到其他线程中
void RewriteTcpServer::incomingConnection(qintptr socketDescriptor) {
	emit sendSocket(socketDescriptor);
}

RewriteTcpServer::~RewriteTcpServer()
{
}
//.h
//服务器监听类
#ifndef __SERVERNETWORK
#define __SERVERNETWORK
#include "QObject"
#include "RewriteTcpServer.h"
#include "SocketFactory.h"
#include "ConnectSqlPool.h"
class ServerNetwork : public QObject
{
	Q_OBJECT

public:
	ServerNetwork(QObject* parent = 0);
	~ServerNetwork();
signals:
	void repetionSendSocketDescriptor(qintptr SocketDescriptor);
protected slots:
	void receptionSocketDescriptor(qintptr SocketDescriptor);
private:
	RewriteTcpServer* listenSocker;//监听类
	SocketFactory   * socketFactory;//socket工厂类
};

#endif  //__SERVERNETWORK
//cpp
#include "ServerNetwork.h"

ServerNetwork::ServerNetwork(QObject* parent) : QObject(parent) {
	socketFactory = new SocketFactory(this);   //初始化工厂类
	listenSocker  = new RewriteTcpServer(this);//客户端监听
	if (listenSocker->listen(QHostAddress::Any, 9090)) {
		qDebug() << "当前网络监听成功......!";
	}
	else {
		qDebug() << listenSocker->errorString();
	}
	connect(listenSocker, &RewriteTcpServer::sendSocket, this, &ServerNetwork::receptionSocketDescriptor);
	connect(this,         &ServerNetwork::repetionSendSocketDescriptor, socketFactory, &SocketFactory::acceptSocketDescriptor);
	QTimer* timer = new QTimer(this);
	connect(timer,        &QTimer::timeout, this, []() {ConnectSqlPool::autoClearMoredb(); qDebug() << "数据库清理定时器启动了"; });
	timer->start(60 * 60 * 1000);
}

void ServerNetwork::receptionSocketDescriptor(qintptr SocketDescriptor) { //将socket描述符发送到工厂类中
	emit repetionSendSocketDescriptor(SocketDescriptor);
}

ServerNetwork::~ServerNetwork() {

}
//.h
#ifndef __SOCKETFACTORY
#define __SOCKETFACTORY
#include <QObject>
#include <QObject>
#include <QList>
#include <QTcpSocket>
#include <QSignalMapper>
#include <QJsonObject>
#include <QJsonDocument>
#include "TranslateJson.h"
#include "ServerLogin.h"
#include "AddPlantInfo.h"
#include <QDataStream>
#include <QThread>
#include "DatasPackaging.h"
class SocketFactory : public QObject {
	Q_OBJECT
public:
	enum {
		LOGIN  = 1001,
		ADD    = 1002,
		SELECT = 1003,
		AMEND  = 1004,
		UPDATE = 1005,
		EXPORT = 1006,
		DELETE = 1007
	};
	SocketFactory(QObject* parent = 0);
	~SocketFactory();
signals:
	void sendExportsignal(QMap<int, QList<QList<QVariant>>> m_map, int index);                          //导入数据线程信号
	void sendSelectsignal(QMap<int, QList<QList<QVariant>>> m_map, int index);                          //返回数据列表线程信号
public slots:
	void acceptSocketDescriptor(qintptr SocketDescriptor);                                              //接收socket描述符
	void dispatchSocketInfo(int index);                                                                 //派发客户端的连接
	void socketState(int index);                                                                        //客户端退出并清除list无效客户端
	void clearDatasSize();                                                                              //清除接收数据
	void feedbackExportInfo(bool result, int index);                                                    //导入信息反馈回客户端
	void feedbackSelectResult(const bool result, const QList<QList<QVariant>> m_lists, const int index);//查询数据反馈
private:
	QList<QTcpSocket*>* listSockt;
	QSignalMapper   * mapper;
	QSignalMapper   * SocketDisconnectedSignals;
	TranslateJson translateJson;
	QThread         * m_thread;
	AddPlantInfo    * m_addPlantInfo;
	DatasPackaging  * datapack;
	qint64 sizeDatas;
	QByteArray countDatas;
};
#endif
//cpp
#include "SocketFactory.h"

SocketFactory::SocketFactory(QObject* parent)
	: QObject(parent), listSockt(new QList<QTcpSocket*>), mapper(new QSignalMapper(this)),
	SocketDisconnectedSignals(new QSignalMapper(this)), datapack(new DatasPackaging(this)) {

	//导入excel多线程
	m_thread = new QThread;
	m_addPlantInfo = new AddPlantInfo;
	m_addPlantInfo->moveToThread(m_thread);
	//初始化交大数据判断字节数
	sizeDatas = 0;
	countDatas.clear();
	//导入线程信号
	connect(this, &SocketFactory::sendExportsignal, m_addPlantInfo, &AddPlantInfo::ExportPlantDatas);
	connect(this, &SocketFactory::sendSelectsignal, m_addPlantInfo, &AddPlantInfo::plantInfoSelect);
	connect(m_addPlantInfo, &AddPlantInfo::sendExportResult, this, &SocketFactory::feedbackExportInfo);
	connect(m_addPlantInfo, &AddPlantInfo::sendPalntResult, this, &SocketFactory::feedbackSelectResult);
	//socket列表
	connect(mapper, &QSignalMapper::mappedInt, this, &SocketFactory::dispatchSocketInfo);
	connect(mapper, &QSignalMapper::mappedInt, this, &SocketFactory::socketState);

	qDebug() << "工厂类启动" << "当前线程ID:" << QThread::currentThreadId();
}

//生产socket并储存进行分类管理
void SocketFactory::acceptSocketDescriptor(qintptr SocketDescriptor) {
	QTcpSocket* tempSocket = new QTcpSocket;
	if (tempSocket->setSocketDescriptor(SocketDescriptor)) {
		qDebug() << "IP:" << tempSocket->peerAddress().toString() << "端口:" << tempSocket->peerPort() << "客户端连接";
		listSockt->append(tempSocket);
		mapper->setMapping(listSockt->last(), listSockt->length() - 1);
		SocketDisconnectedSignals->setMapping(listSockt->last(), listSockt->length() - 1);
		connect(listSockt->last(), SIGNAL(readyRead()), mapper, SLOT(map()));
		connect(listSockt->last(), SIGNAL(stateChanged(QAbstractSocket::SocketState)), mapper, SLOT(map()));
	}
	else {
		qDebug() << "连接错误,错误原因:" << tempSocket->errorString();
	}
}
//派发socket
void SocketFactory::dispatchSocketInfo(int index) {
	//大量数据导致readAll无法全部接收,进行多次接收的判断
	QByteArray str = listSockt->at(index)->readAll();
	if (!str.isEmpty()) {
		if (sizeDatas == 0) {
			//获取头信息
			QDataStream in(str);
			in >> sizeDatas;
			qDebug() << "接收的数据大小" << sizeDatas;
		}
		if (countDatas.size() < sizeDatas) {
			countDatas.append(str);
			qDebug() << "接收大量数据的字节数:" << countDatas.size();
		}
		if (sizeDatas == countDatas.size()) {
			QDataStream indata(countDatas);
			qint64 headersize;
			QMap<int, QList<QList<QVariant>>> m_datas;
			indata.setVersion(QDataStream::Qt_6_2);
			indata >> headersize >> m_datas;
			switch (m_datas.firstKey()) {

			case LOGIN: {
				ServerLogin login;
				login.sendLoginInfo(listSockt->at(index), m_datas);
				clearDatasSize();
				break;
			}
			case ADD: {
				AddPlantInfo addPlant;
				addPlant.addplantinfo(listSockt->at(index), m_datas);
				clearDatasSize();
				break;
			}
			case EXPORT: {
				m_thread->start();//线程反馈后的信息回复
				emit sendExportsignal(m_datas, index);
				clearDatasSize();
				break;
			}
			case SELECT: {
				m_thread->start();//完成查询信息处理
				sendSelectsignal(m_datas, index);
				clearDatasSize();
				break;
			}
			case DELETE: {
				AddPlantInfo addPlant;
				addPlant.deletePlantInfo(listSockt->at(index), m_datas);
				clearDatasSize();
				break;
			}
			case UPDATE: {
				qDebug() << "更新数据进行";
				AddPlantInfo updatePlant;
				updatePlant.updatePlantInfo(listSockt->at(index), m_datas);
				clearDatasSize();
				break;
			}
			default:
				break;
			}
		}
	}
}

//清除无效客户端
void SocketFactory::socketState(int index) {
	if (listSockt->at(index)->state() == QAbstractSocket::UnconnectedState) {
		//如果当前客户端断开或无效客户端时,关闭当前客户端并从list中删除
		QTcpSocket* closeSocket = listSockt->at(index);
		qDebug() << "IP:" << listSockt->at(index)->peerAddress().toString().trimmed()
			<< "端口:" << listSockt->at(index)->peerPort() << "客户端退出了";
		mapper->removeMappings(closeSocket);
		SocketDisconnectedSignals->removeMappings(closeSocket);
		closeSocket->close();
		listSockt->removeAt(index);
	}
}

void SocketFactory::clearDatasSize() {
	sizeDatas  = 0;
	countDatas = NULL;
}

//导入信息反馈函数
void SocketFactory::feedbackExportInfo(bool result, int index) {
	QByteArray m_by;
	datapack->datasPackging(1003, result, m_by);
	if (!m_by.isEmpty()) {
		listSockt->at(index)->write(m_by, m_by.size());
	}
	m_thread->quit();
	m_thread->wait();
}

//返回车间信息表
void SocketFactory::feedbackSelectResult(const bool result, const QList<QList<QVariant>> m_lists, const int index) {
	QByteArray m_by;
	datapack->datasPackging(1004, m_lists, m_by);
	if (!m_by.isEmpty()) {
		listSockt->at(index)->write(m_by, m_by.size());
	}
	m_thread->quit();
	m_thread->wait();
}

SocketFactory::~SocketFactory() {
	delete m_thread;
	delete m_addPlantInfo;
	delete listSockt;
}

举报

相关推荐

0 条评论