QTcpSocket服务器多线程

在这里插入图片描述
服务器端连接多个客户端,接收客户端信息,返回客户端信息

TcpServer 是在主线程中,重写 incomingConnection函数,每次有新的客户端连接服务器将会自动调用此函数,在此函数中构建新的TcpSocket,并且保存,主线程和子线程通过信号和槽机制通信,使用套接字识别是哪一个socket

多线程机制使用moveTothread,Qt官方更推荐此类方式


class MyTcpSever : public QTcpServer
{
	Q_OBJECT
public:
	explicit MyTcpSever(QObject* parent = nullptr);
	//开启监听
	bool startSeverListen(QString sHostPort);
	// 当有新连接可用时,QTcpServer将调用此虚拟函数
	void incomingConnection(qintptr socketDescriptor) override;

private slots:
	//有客户端断开连接
	void _clientDisconnected(qintptr socketDescriptor);

private:
	// 连接到服务器的客户端链表
	QList<MyTcpSocket*> m_tcpClientSocketList;
};

class MyTcpSocket : public QObject
{
	Q_OBJECT
public:
	MyTcpSocket(qintptr socketDescriptor, QObject* parent = nullptr);
	qintptr getSocketDescriptor();
signals:
	// 通知服务器 客户端掉线
	void clientDisconnect(qintptr socketDescriptor);
private slots:
	void _initSocket();
	// 处理readyRead信号读取数据
	void _receiveData();
	// 用来处理客户端断开连接触发disconnected信号
	void _clientDisconnected();
private:
	QTcpSocket* m_tcpSocket;
	QThread* m_thread;
	qintptr m_socketDescriptor;
};

MyTcpSever::MyTcpSever(QObject* parent)
{
}

bool MyTcpSever::startSeverListen(QString sHostPort)
{
	//监听端口
	if (listen(QHostAddress::Any, sHostPort.toInt()))
	{
		return true;
	}
	return false;
}

void MyTcpSever::incomingConnection(qintptr socketDescriptor)
{
	//只要有新的连接就生成一个新的通信套接字
	auto tcpClientSocket = new MyTcpSocket(socketDescriptor, this);

	//将这个套接字加入客户端套接字列表中
	m_tcpClientSocketList.append(tcpClientSocket);

	//处理客户端掉线
	connect(tcpClientSocket, &MyTcpSocket::clientDisconnect, this, &MyTcpSever::_clientDisconnected);
}

void MyTcpSever::_clientDisconnected(qintptr socketDescriptor)
{
	//如果有客户端断开连接, 就将列表中的套接字删除
	for (int i = 0; i < m_tcpClientSocketList.count(); i++)
	{
		if (m_tcpClientSocketList.value(i)->getSocketDescriptor() == socketDescriptor)
		{
			m_tcpClientSocketList.removeAt(i);
			return;
		}
	}
}

MyTcpSocket::MyTcpSocket(qintptr socketDescriptor, QObject* parent)
{
	qDebug() << u8"主线程" << QThread::currentThread();
	m_socketDescriptor = socketDescriptor;
	m_thread = new QThread;
	this->moveToThread(m_thread);
	connect(m_thread, &QThread::started, this, &MyTcpSocket::_initSocket);
	m_thread->start();
}

qintptr MyTcpSocket::getSocketDescriptor()
{
	return m_socketDescriptor;
}

void MyTcpSocket::_initSocket()
{
	//socket放到子线程初始化
	m_tcpSocket = new QTcpSocket;
	m_tcpSocket->setSocketDescriptor(m_socketDescriptor);
	//接收到tcpclientsocket发送过来信息
	connect(m_tcpSocket, &QTcpSocket::readyRead, this, &MyTcpSocket::_receiveData);
	//客户端断开连接时会触发信号disconnected()
	connect(m_tcpSocket, &QTcpSocket::disconnected, this, &MyTcpSocket::_clientDisconnected);
}

void MyTcpSocket::_receiveData()
{
	int iPort = m_tcpSocket->peerPort();
	qint64 iMaxLength = 1024;
	QByteArray baArray = m_tcpSocket->readAll(); //把socket中的消息读出
	int i = 0;
	while (baArray.length() != 0)
	{
		QString sMsg = baArray.left(iMaxLength);
		baArray = baArray.remove(0, iMaxLength);
		i++;
	
		qDebug() << u8"子线程" << QThread::currentThread() << u8"收到:" + sMsg;
		m_tcpSocket->write("ok");//服务器向客户端发送指定消息
	}
}

void MyTcpSocket::_clientDisconnected()
{
	emit clientDisconnect(m_tcpSocket->socketDescriptor());
}

调用的时候只需要

m_tcpServer = new MyTcpSever(this); //创建一个服务器类
m_tcpServer->startSeverListen(需要监听的端口号)
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,创建一个TCP服务器需要使用QTQTcpServer类。然后,为了支持多线程,我们需要使用QTQThread类来创建新的线程,并在每个新线程中运行QTQTcpSocket类。 以下是一个简单的示例代码,可以创建一个多线程的TCP服务器: ``` #include <QTcpServer> #include <QTcpSocket> #include <QThread> class TcpServer : public QTcpServer { Q_OBJECT public: explicit TcpServer(QObject *parent = nullptr); protected: void incomingConnection(qintptr socketDescriptor) override; }; class TcpSocket : public QTcpSocket { Q_OBJECT public: explicit TcpSocket(QObject *parent = nullptr); public slots: void readData(); private: qintptr socketDescriptor; }; class WorkerThread : public QThread { Q_OBJECT public: explicit WorkerThread(qintptr socketDescriptor, QObject *parent = nullptr); protected: void run() override; private: qintptr socketDescriptor; }; TcpServer::TcpServer(QObject *parent) : QTcpServer(parent) { } void TcpServer::incomingConnection(qintptr socketDescriptor) { WorkerThread *worker = new WorkerThread(socketDescriptor, this); worker->start(); } TcpSocket::TcpSocket(QObject *parent) : QTcpSocket(parent) { connect(this, &TcpSocket::readyRead, this, &TcpSocket::readData); } void TcpSocket::readData() { QByteArray data = readAll(); // 处理接收到的数据 } WorkerThread::WorkerThread(qintptr socketDescriptor, QObject *parent) : QThread(parent), socketDescriptor(socketDescriptor) { } void WorkerThread::run() { TcpSocket *socket = new TcpSocket(); socket->setSocketDescriptor(socketDescriptor); exec(); } ``` 在这个示例中,TcpServer类继承自QTcpServer,用于创建TCP服务器。在incomingConnection()函数中,每当有新的连接时,就会创建一个新的WorkerThread线程,并将连接的socket描述符传递给它。 WorkerThread类继承自QThread,用于在新的线程中运行TcpSocket类。在run()函数中,我们创建一个新的TcpSocket对象,并使用setSocketDescriptor()函数将连接的socket描述符传递给它。然后,我们启动线程的事件循环,以便TcpSocket对象可以处理接收到的数据。 TcpSocket类继承自QTcpSocket,用于处理与客户端的通信。在readData()槽函数中,我们读取接收到的数据并进行处理。 注意,以上代码仅为示例代码,可能需要根据实际情况进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值